package com.hskn.hss.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hskn.hss.core.constant.Constants;
import com.hskn.hss.module.carPlan.entity.CarPlan;
import com.hskn.hss.module.carPlan.mapper.CarPlanMapper;
import com.hskn.hss.module.carPlan.service.CarPlanService;
import com.hskn.hss.module.carPlanCar.entity.CarPlanCar;
import com.hskn.hss.module.carPlanCar.mapper.CarPlanCarMapper;
import com.hskn.hss.module.carPlanCollectPoint.entity.CarPlanCollectPoint;
import com.hskn.hss.module.carPlanCollectPoint.mapper.CarPlanCollectPointMapper;
import com.hskn.hss.module.carPlanCollectStand.entity.CarPlanCollectStand;
import com.hskn.hss.module.carPlanCollectStand.mapper.CarPlanCollectStandMapper;
import com.hskn.hss.module.carPlanProcessStand.entity.CarPlanProcessStand;
import com.hskn.hss.module.carPlanProcessStand.mapper.CarPlanProcessStandMapper;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrack.mapper.CarTrackMapper;
import com.hskn.hss.module.carTrack.service.CarTrackService;
import com.hskn.hss.module.carTrackRevise.service.CarTrackReviseService;
import com.hskn.hss.module.carviolation.service.ICarViolationService;
import com.hskn.hss.module.caseprocess.entity.CaseProcess;
import com.hskn.hss.module.caseprocess.mapper.CaseProcessMapper;
import com.hskn.hss.module.cases.entity.Cases;
import com.hskn.hss.module.cases.mapper.CasesMapper;
import com.hskn.hss.module.cases.service.ICasesService;
import com.hskn.hss.module.depart.entity.SysDepart;
import com.hskn.hss.module.depart.service.impl.SysDepartServiceImpl;
import com.hskn.hss.module.empPlan.entity.EmpPlan;
import com.hskn.hss.module.empPlan.mapper.EmpPlanMapper;
import com.hskn.hss.module.empPlanDate.entity.EmpPlanDate;
import com.hskn.hss.module.empPlanDate.mapper.EmpPlanDateMapper;
import com.hskn.hss.module.empPlanEmployee.entity.EmpPlanEmployee;
import com.hskn.hss.module.empPlanEmployee.mapper.EmpPlanEmployeeMapper;
import com.hskn.hss.module.empWorkPoints.entity.EmpWorkPoints;
import com.hskn.hss.module.empWorkPoints.service.IEmpWorkPointsService;
import com.hskn.hss.module.employeePunchCard.entity.EmployeePunchCard;
import com.hskn.hss.module.employeePunchCard.mapper.EmployeePunchCardMapper;
import com.hskn.hss.module.employeePunchCard.service.EmployeePunchCardService;
import com.hskn.hss.module.employeePunchCard.service.impl.EmployeePunchCardServiceImpl;
import com.hskn.hss.module.employeeTrack.entity.EmployeeTrack;
import com.hskn.hss.module.employeeTrack.mapper.EmployeeTrackMapper;
import com.hskn.hss.module.grid.entity.Grid;
import com.hskn.hss.module.grid.mapper.GridMapper;
import com.hskn.hss.module.grid.service.IGridService;
import com.hskn.hss.module.gridBindCheckWork.entity.GridBindCheckwork;
import com.hskn.hss.module.gridBindCheckWork.service.GridBindCheckWorkService;
import com.hskn.hss.module.gridBindSnapshot.entity.GridBindSnapshot;
import com.hskn.hss.module.gridBindSnapshot.mapper.GridBindSnapshotMapper;
import com.hskn.hss.module.gridBindSnapshot.service.GridBindSnapshotService;
import com.hskn.hss.module.gridCheckWork.entity.GridCheckwork;
import com.hskn.hss.module.gridCheckWork.mapper.GridCheckWorkMapper;
import com.hskn.hss.module.gridCheckWorkSnapshot.entity.GridCheckworkSnapshot;
import com.hskn.hss.module.gridCheckWorkSnapshot.mapper.GridCheckWorkSnapshotMapper;
import com.hskn.hss.module.gridCheckWorkSnapshot.service.GridCheckWorkSnapshotService;
import com.hskn.hss.module.gridSnapshot.entity.GridSnapshot;
import com.hskn.hss.module.gridSnapshot.mapper.GridSnapshotMapper;
import com.hskn.hss.module.gridSnapshot.service.GridSnapshotService;
import com.hskn.hss.module.gridbind.entity.GridBind;
import com.hskn.hss.module.gridbind.mapper.GridBindMapper;
import com.hskn.hss.module.kfkcarlocation.service.IKfkCarLocationService;
import com.hskn.hss.module.rptCarWork.entity.RptCarWork;
import com.hskn.hss.module.rptCarWork.mapper.RptCarWorkMapper;
import com.hskn.hss.module.rptCarWorkFacility.entity.RptCarWorkFacility;
import com.hskn.hss.module.rptCarWorkFacility.mapper.RptCarWorkFacilityMapper;
import com.hskn.hss.module.rptEmployeeWork.entity.RptEmployeeWork;
import com.hskn.hss.module.rptEmployeeWork.mapper.RptEmployeeWorkMapper;
import com.hskn.hss.module.rptEmployeeWork.service.RptEmployeeWorkService;
import com.hskn.hss.module.sysDictType.entity.SysDictType;
import com.hskn.hss.module.sysDictType.service.SysDictTypeService;
import com.hskn.hss.module.tlcar.entity.TlCar;
import com.hskn.hss.module.tlcar.mapper.TlCarMapper;
import com.hskn.hss.module.tlcar.service.ITlCarService;
import com.hskn.hss.module.tlemployee.entity.TlEmployee;
import com.hskn.hss.module.tlemployee.mapper.TlEmployeeMapper;
import com.hskn.hss.module.tlfacilities.entity.TlFacilities;
import com.hskn.hss.module.tlfacilities.mapper.TlFacilitiesMapper;
import com.hskn.hss.module.tlfacilities.service.ITlFacilitiesService;
import com.hskn.hss.module.tlopetation.entity.TlOperation;
import com.hskn.hss.module.tlopetation.mapper.TlOperationMapper;
import com.hskn.hss.module.workgroup.entity.WorkGroup;
import com.hskn.hss.module.workgroup.mapper.WorkGroupMapper;
import com.hskn.hss.module.workkaoqin.entity.WorkKaoqin;
import com.hskn.hss.module.workkaoqin.mapper.WorkKaoqinMapper;
import com.hskn.hss.module.workrule.entity.WorkRule;
import com.hskn.hss.module.workrule.mapper.WorkRuleMapper;
import com.hskn.hss.utils.*;
import com.hskn.hss.utils.redis.RedisUtil;
import com.hskn.hss.utils.redis.key.CarAlarmOilTimeKeyToday;
import com.hskn.hss.utils.redis.key.CarTrackNoReviseListKey;
import com.hskn.hss.utils.redis.key.EndWorkPunchCardTimeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DateUnit.MINUTE;
import static java.util.stream.Collectors.toList;

@Slf4j
@Configuration
@EnableScheduling
public class HssTask {
    @Autowired
    LocationUtils locationUtils;
    @Autowired
    IGridService gridService;
    @Autowired
    IKfkCarLocationService kfkCarLocationService;
    @Autowired
    ICarViolationService carViolationService;
    @Autowired
    ITlFacilitiesService tlFacilitiesService;
    @Resource
    RptEmployeeWorkMapper rptEmployeeWorkMapper;
    @Resource
    RptCarWorkMapper rptCarWorkMapper;
    @Resource
    TlEmployeeMapper tlEmployeeMapper;
    @Resource
    GridMapper gridMapper;
    @Resource
    GridCheckWorkMapper gridCheckworkMapper;
    @Resource
    WorkRuleMapper workRuleMapper;
    @Autowired
    ITlCarService iTlCarService;
    @Autowired
    CarTrackService carTrackService;
    @Resource
    CarTrackMapper carTrackMapper;
    @Autowired
    CarTrackReviseService carTrackReviseService;
    @Resource
    EmployeeTrackMapper employeeTrackMapper;
    @Autowired
    LocationUtils locationUtil;
    private Double distanceFlag = 5.0;
    @Resource
    private CasesMapper casesMapper;
    @Autowired
    private ICasesService casesService;
    @Resource
    private CaseProcessMapper caseProcessMapper;
    @Resource
    private WorkGroupMapper workGroupMapper;
    @Resource
    private WorkKaoqinMapper workKaoqinMapper;
    @Resource
    private TlCarMapper tlCarMapper;
    @Resource
    private GridSnapshotMapper gridSnapshotMapper;
    @Resource
    private EmpPlanDateMapper empPlanDateMapper;
    @Resource
    private EmpPlanMapper empPlanMapper;
    @Resource
    private EmpPlanEmployeeMapper empPlanEmployeeMapper;
    @Resource
    private CarPlanMapper carPlanMapper;
    @Resource
    private CarPlanCarMapper carPlanCarMapper;
    @Resource
    private TlOperationMapper tlOperationMapper;
    @Resource
    private CarPlanCollectPointMapper carPlanCollectPointMapper;
    @Resource
    private CarPlanService carPlanService;
    @Resource
    private TlFacilitiesMapper tlFacilitiesMapper;
    @Resource
    private CarPlanCollectStandMapper carPlanCollectStandMapper;
    @Resource
    private CarPlanProcessStandMapper carPlanProcessStandMapper;
    @Resource
    private RptCarWorkFacilityMapper rptCarWorkFacilityMapper;
    @Resource
    private GridBindMapper gridBindMapper;
    @Resource
    private GridBindSnapshotMapper gridBindSnapshotMapper;
    @Resource
    private GridCheckWorkMapper gridCheckWorkMapper;
    @Resource
    private GridCheckWorkSnapshotMapper gridCheckWorkSnapshotMapper;
    @Resource
    private GridBindCheckWorkService gridBindCheckWorkService;
    @Resource
    private RptEmployeeWorkService rptEmployeeWorkService;
    @Resource
    private IEmpWorkPointsService empWorkPointsService;
    @Resource
    private SysDictTypeService sysDictTypeService;
    @Resource
    private EmployeePunchCardServiceImpl employeePunchCardService;
    @Resource
    private EmployeePunchCardMapper employeePunchCardMapper;
    @Resource
    private GridSnapshotService gridSnapshotService;
    @Autowired
    private GridCheckWorkSnapshotService gridCheckWorkSnapshotService;
    @Autowired
    private GridBindSnapshotService gridBindSnapshotService;
    @Autowired
    private SysDepartServiceImpl sysDepartService;

    @Value("${switch.timed_task}")
    private Boolean timed_task;

    @Scheduled(cron = "0 0 23 * * ?")
    public void initCarAttendance() {
        if (timed_task) {
            try {
                log.info("==================车辆考勤-初始化=================start=");
                /** 车辆考勤 **/
                List<TlCar> tlCarList = iTlCarService.list();
                for (TlCar tlCar : tlCarList) {
                    tlCar.setAttendance(1);
                    tlCar.setShiftStatus(1);
                    tlCar.setOnguardstatus(1);
                    tlCarMapper.updateById(tlCar);
                }
                List<CarPlan> carPlanAllList = new ArrayList<>();

                // 1.查询机械清扫、垃圾清运、垃圾转运作业
                Date date = new Date();
                Calendar c = Calendar.getInstance();
                c.setTime(date);
                c.add(Calendar.DAY_OF_MONTH, 1);
                date = c.getTime();
                SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
                String calendarDate = sdf1.format(date);

                List<WorkGroup> workGroupList = workGroupMapper.selectList(new QueryWrapper<>());
                Map<String, WorkGroup> workGroupMap = workGroupList.stream().collect(Collectors.groupingBy(WorkGroup::getWorkGroupId, Collectors.collectingAndThen(toList(), workGroups -> workGroups.get(0))));

                List<WorkRule> workRuleList = workRuleMapper.selectList(new QueryWrapper<>());
                Map<String, WorkRule> workRuleMap = workRuleList.stream().collect(Collectors.groupingBy(WorkRule::getWorkRuleId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));

                List<TlOperation> operationList = tlOperationMapper.selectList(new QueryWrapper<>());
                Map<String, TlOperation> operationMap = operationList.stream().collect(Collectors.groupingBy(TlOperation::getId, Collectors.collectingAndThen(toList(), values -> values.get(0))));


                QueryWrapper<CarPlanCar> carPlanCarQueryWrapper = new QueryWrapper<>();
                List<CarPlanCar> carPlanCarList = carPlanCarMapper.selectList(carPlanCarQueryWrapper);
                Map<String, List<CarPlanCar>> carPlanCarMap = carPlanCarList.stream().collect(Collectors.groupingBy(CarPlanCar::getCarPlanId));

                List<TlFacilities> tlFacilitiesList = tlFacilitiesMapper.selectList(new QueryWrapper<>());
                Map<String, TlFacilities> tlFacilitiesMap = tlFacilitiesList.stream().collect(Collectors.groupingBy(TlFacilities::getId, Collectors.collectingAndThen(toList(), values -> values.get(0))));

                QueryWrapper<CarPlanCollectPoint> carPlanCollectPointQueryWrapper = new QueryWrapper<>();
                List<CarPlanCollectPoint> carPlanCollectPointList = carPlanCollectPointMapper.selectList(carPlanCollectPointQueryWrapper);
                Map<String, List<CarPlanCollectPoint>> carPlanCollectPointMap = carPlanCollectPointList.stream().collect(Collectors.groupingBy(CarPlanCollectPoint::getCarPlanId));

                QueryWrapper<CarPlanCollectStand> carPlanCollectStandQueryWrapper = new QueryWrapper<>();
                List<CarPlanCollectStand> carPlanCollectStandList = carPlanCollectStandMapper.selectList(carPlanCollectStandQueryWrapper);
                Map<String, List<CarPlanCollectStand>> carPlanCollectStandMap = carPlanCollectStandList.stream().collect(Collectors.groupingBy(CarPlanCollectStand::getCarPlanId));

                QueryWrapper<CarPlanProcessStand> carPlanProcessStandQueryWrapper = new QueryWrapper<>();
                List<CarPlanProcessStand> carPlanProcessStandList = carPlanProcessStandMapper.selectList(carPlanProcessStandQueryWrapper);
                Map<String, List<CarPlanProcessStand>> carPlanProcessStandMap = carPlanProcessStandList.stream().collect(Collectors.groupingBy(CarPlanProcessStand::getCarPlanId));


                QueryWrapper<CarPlan> carPlanQueryWrapper = new QueryWrapper<>();
                carPlanQueryWrapper.lambda().le(CarPlan::getWorkStartDate, calendarDate);
                carPlanQueryWrapper.lambda().ge(CarPlan::getWorkEndDate, calendarDate);
//                carPlanQueryWrapper.lambda().eq(CarPlan::getType, 2);
                carPlanQueryWrapper.lambda().eq(CarPlan::getIsEnable, "1");
                List<CarPlan> carPlanList = carPlanMapper.selectList(carPlanQueryWrapper);
                for (CarPlan carPlan : carPlanList) {
                    boolean exist = TimeUtil.checkPeriodDate(DateUtil.parse(calendarDate), StringUtils.StringToDate3(carPlan.getWorkStartDate()), StringUtils.StringToDate3(carPlan.getWorkEndDate()), carPlan.getWorkCycle());
                    if (exist) {
                        carPlanAllList.add(carPlan);
                    }
                }

                for (CarPlan carPlan : carPlanAllList) {
                    List<String> carIds = new ArrayList<>();
                    if (carPlan.getType() == 1) {
                        List<CarPlanCar> carPlanCarList1 = carPlanCarMap.get(carPlan.getId());
                        if (null != carPlanCarList1) {
                            for (CarPlanCar carPlanCar : carPlanCarList1) {
                                carIds.add(carPlanCar.getCarId());
                            }
                        }
                        //如果可以查询车辆id 说明有排班
                        List<TlCar> tlCarShiftList = tlCarMapper.selectInIdCarIds(carIds);
                        for (TlCar tlCar : tlCarShiftList) {
                            tlCar.setShiftStatus(0);
                            tlCarMapper.updateById(tlCar);
                        }

                        if (null == carIds || carIds.isEmpty()) {
                            continue;
                        }
                        Grid grid = gridMapper.selectById(carPlan.getGridId());
                        if (null == grid) {
                            log.error("---不存在此网格，不初始化车辆考勤表，gridId:{},carPlanId:{}，carIdsStr:{}", carPlan.getGridId(), carPlan.getId(), String.join(",", carIds));
                            continue;
                        }
                        RptCarWork rptCarWork = new RptCarWork();
                        rptCarWork.setPlanId(carPlan.getId());
                        rptCarWork.setWorkCycle(carPlan.getWorkCycle());
                        rptCarWork.setPlanName(carPlan.getPlanName());
                        rptCarWork.setGridId(carPlan.getGridId());
                        rptCarWork.setGridName(grid.getName());
                        WorkGroup workGroup = workGroupMap.get(carPlan.getWorkGroupId());
                        if (null != workGroup) {
                            rptCarWork.setGroupId(workGroup.getWorkGroupId());
                            rptCarWork.setGroupName(workGroup.getName());
                        }
                        WorkRule workRule = workRuleMap.get(carPlan.getWorkRuleId());
                        if (null != workRule) {
                            rptCarWork.setRuleId(workRule.getWorkRuleId());
                            rptCarWork.setRuleName(workRule.getRuleName());
                        }
                        rptCarWork.setExpectOilConsumption(null == carPlan.getExpectOilConsumption() ? BigDecimal.ZERO : carPlan.getExpectOilConsumption());
                        rptCarWork.setExpectWaterConsumption(null == carPlan.getExpectWaterConsumption() ? BigDecimal.ZERO : carPlan.getExpectWaterConsumption());
                        rptCarWork.setExpectWorkTime(null == carPlan.getExpectTimeConsumption() ? BigDecimal.ZERO : carPlan.getExpectTimeConsumption());
                        rptCarWork.setWorkType(2);
                        //计划总进度，机械清扫为总里程，其他为收集点数量
                        Double km = null == grid.getKm() ? 0 : grid.getKm();
                        Integer tangCi = null == carPlan.getWorkTrip() ? 0 : carPlan.getWorkTrip();
                        rptCarWork.setAllProgress(km.intValue() * tangCi);
                        TlOperation tlOperation = operationMap.get(carPlan.getWorkTypeId());
                        if (null != tlOperation) {
                            rptCarWork.setWorkTypeId(tlOperation.getId());
                            rptCarWork.setWorkTypeName(tlOperation.getOperationtype());
                        }
                        rptCarWork.setCarWorkType(carPlan.getWorkType());
                        rptCarWork.setTangCi(tangCi);
                        handlePlanAndSave(DateUtil.parse(calendarDate), rptCarWork, carPlan.getWorkGroupId(), carIds, tlFacilitiesMap, carPlanCollectPointMap, carPlanCollectStandMap, carPlanProcessStandMap);
                    } else if (carPlan.getType() == 2) {

                        //垃圾清运
                        List<CarPlanCar> carPlanCarList1 = carPlanCarMap.get(carPlan.getId());
                        if (null != carPlanCarList1) {
                            for (CarPlanCar carPlanCar : carPlanCarList1) {
                                carIds.add(carPlanCar.getCarId());
                            }
                        }
                        List<TlCar> tlCarShiftList = tlCarMapper.selectInIdCarIds(carIds);
                        for (TlCar tlCar : tlCarShiftList) {
                            tlCar.setShiftStatus(0);
                            tlCarMapper.updateById(tlCar);
                        }
                        if (null == carIds || carIds.isEmpty()) {
                            continue;
                        }
                        Grid grid = gridMapper.selectById(carPlan.getGridId());
                        if (null == grid) {
                            log.error("---不存在此网格，不初始化车辆考勤表，gridId:{},carPlanId:{}，carIdsStr:{}", carPlan.getGridId(), carPlan.getId(), String.join(",", carIds));
                            continue;
                        }
                        RptCarWork rptCarWork = new RptCarWork();
                        rptCarWork.setPlanId(carPlan.getId());
                        rptCarWork.setWorkCycle(carPlan.getWorkCycle());

                        rptCarWork.setPlanName(carPlan.getPlanName());
                        rptCarWork.setGridId(carPlan.getGridId());
                        rptCarWork.setGridName(grid.getName());
                        WorkGroup workGroup = workGroupMap.get(carPlan.getWorkGroupId());
                        if (null != workGroup) {
                            rptCarWork.setGroupId(workGroup.getWorkGroupId());
                            rptCarWork.setGroupName(workGroup.getName());
                        }
                        WorkRule workRule = workRuleMap.get(carPlan.getWorkRuleId());
                        if (null != workRule) {
                            rptCarWork.setRuleId(workRule.getWorkRuleId());
                            rptCarWork.setRuleName(workRule.getRuleName());
                        }
                        rptCarWork.setExpectWorkTime(null == carPlan.getExpectTimeConsumption() ? BigDecimal.ZERO : carPlan.getExpectTimeConsumption());
                        rptCarWork.setWorkType(3);
                        handlePlanAndSave(DateUtil.parse(calendarDate), rptCarWork, carPlan.getWorkGroupId(), carIds, tlFacilitiesMap, carPlanCollectPointMap, carPlanCollectStandMap, carPlanProcessStandMap);
                    } else {
                        //垃圾转运
                        List<CarPlanCar> carPlanCarList1 = carPlanCarMap.get(carPlan.getId());
                        if (null != carPlanCarList1) {
                            for (CarPlanCar carPlanCar : carPlanCarList1) {
                                carIds.add(carPlanCar.getCarId());
                            }
                        }
                        List<TlCar> tlCarShiftList = tlCarMapper.selectInIdCarIds(carIds);
                        for (TlCar tlCar : tlCarShiftList) {
                            tlCar.setShiftStatus(0);
                            tlCarMapper.updateById(tlCar);
                        }
                        if (null == carIds || carIds.isEmpty()) {
                            continue;
                        }
                        Grid grid = gridMapper.selectById(carPlan.getGridId());
                        if (null == grid) {
                            log.error("---不存在此网格，不初始化车辆考勤表，gridId:{},carPlanId:{}，carIdsStr:{}", carPlan.getGridId(), carPlan.getId(), String.join(",", carIds));
                            continue;
                        }
                        RptCarWork rptCarWork = new RptCarWork();
                        rptCarWork.setId(StringUtils.uuid());
                        rptCarWork.setPlanId(carPlan.getId());
                        rptCarWork.setPlanName(carPlan.getPlanName());
                        rptCarWork.setGridId(carPlan.getGridId());
                        rptCarWork.setGridName(grid.getName());
                        WorkGroup workGroup = workGroupMap.get(carPlan.getWorkGroupId());
                        if (null != workGroup) {
                            rptCarWork.setGroupId(workGroup.getWorkGroupId());
                            rptCarWork.setGroupName(workGroup.getName());
                        }
                        WorkRule workRule = workRuleMap.get(carPlan.getWorkRuleId());
                        if (null != workRule) {
                            rptCarWork.setRuleId(workRule.getWorkRuleId());
                            rptCarWork.setRuleName(workRule.getRuleName());
                        }
                        rptCarWork.setExpectMileage(null != carPlan.getExpectMileage() ? BigDecimal.ZERO : carPlan.getExpectMileage());
                        rptCarWork.setWorkType(4);
                        handlePlanAndSave(DateUtil.parse(calendarDate), rptCarWork, carPlan.getWorkGroupId(), carIds, tlFacilitiesMap, carPlanCollectPointMap, carPlanCollectStandMap, carPlanProcessStandMap);
                    }

                }
            } catch (ParseException e) {
                e.printStackTrace();
                log.error("ERROR", e);
            }
        }
        log.info("==================车辆考勤-初始化=================end=");
    }


    private void handlePlanAndSave(Date now, RptCarWork rptCarWork, String workGroupId, List<String> carIds,
                                   Map<String, TlFacilities> tlFacilitiesMap, Map<String, List<CarPlanCollectPoint>> carPlanCollectPointMap,
                                   Map<String, List<CarPlanCollectStand>> carPlanCollectStandMap, Map<String, List<CarPlanProcessStand>> carPlanProcessStandMap) {

        WorkGroup workGroup = workGroupMapper.selectById(workGroupId);
        if (null != workGroup) {
            //勤类型，固定班1，冬夏班2
            Integer kaoqinType = workGroup.getKaoqinType();
            //1:夏季,2:冬季
            String season = DateUtils.getCurrentSeason(now);
            String kaoqinIds = workGroup.getKaoqinIds();
            if (StringUtils.isEmpty(kaoqinIds)) {
                return;
            }
            List<WorkKaoqin> workKaoqinList = workKaoqinMapper.selectBatchIds(Arrays.asList(kaoqinIds.split(",")));
            for (String carId : carIds) {
                String workDate = DateUtil.format(now, "yyyy-MM-dd");

                //重复判断
                QueryWrapper<RptCarWork> rptCarWrokWrapper = new QueryWrapper<>();
                rptCarWrokWrapper.lambda().eq(RptCarWork::getCarId, carId);
                rptCarWrokWrapper.lambda().eq(RptCarWork::getPlanId, rptCarWork.getPlanId());
                rptCarWrokWrapper.lambda().eq(RptCarWork::getWorkDate, workDate);
                List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWrokWrapper);
                if (!CollectionUtils.isEmpty(rptCarWorkList)) {
                    continue;
                }

                TlCar tlCar = tlCarMapper.selectByIdWithCarType(carId);
                if (null == tlCar) {
                    continue;
                }
                for (WorkKaoqin workKaoqin : workKaoqinList) {
                    try {
                        String planStartTime = null;//排班开始时间
                        String planEndTime = null;//排班结束时间
                        if (1 == kaoqinType) {//固定班
                            planStartTime = workKaoqin.getSbsj();
                            planEndTime = workKaoqin.getXbsj();
                        } else if (2 == kaoqinType) {//冬夏班
                            if ("summer".equals(season)) {
                                planStartTime = workKaoqin.getXsbsj();
                                planEndTime = workKaoqin.getXxbsj();
                            } else if ("winter".equals(season)) {
                                planStartTime = workKaoqin.getDsbsj();
                                planEndTime = workKaoqin.getDxbsj();
                            }
                        }
                        rptCarWork.setId(StringUtils.uuid());
                        rptCarWork.setCarId(carId);
                        rptCarWork.setCarNum(tlCar.getCarnumber());
                        rptCarWork.setCarType(tlCar.getCarTypeName());
                        rptCarWork.setWorkDate(workDate);//排班日期
                        rptCarWork.setWorkMonth(DateUtil.format(now, "yyyy-MM"));//排班月份
                        rptCarWork.setDepartmentId(tlCar.getDeptid());
                        System.out.println(workDate + " " + planStartTime);
                        if (null != planStartTime) {
                            rptCarWork.setPlanStartTime(DateUtil.parse(workDate + " " + planStartTime, "yyyy-MM-dd HH:mm"));
                        }
                        if (null != planEndTime) {
                            rptCarWork.setPlanEndTime(DateUtil.parse(workDate + " " + planEndTime, "yyyy-MM-dd HH:mm"));
                        }
                        rptCarWork.setCreateTime(new Date());
                        rptCarWork.setCarName(tlCar.getCarnumber() + "[" + tlCar.getCarTypeName() + "]");
                        rptCarWork.setShiftId(workKaoqin.getWorkKaoqinId());
                        rptCarWork.setShiftName(workKaoqin.getName());
//                        rptCarWork.set
                        // 保存车辆考勤

                        //生成从表
                        if (rptCarWork.getWorkType() == 3) {

                            List<String> carPlanCollectPointIds = new ArrayList<>();
                            List<CarPlanCollectPoint> carPlanCollectPointList1 = carPlanCollectPointMap.get(rptCarWork.getPlanId());
                            if (null != carPlanCollectPointList1) {
                                for (CarPlanCollectPoint carPlanCollectPoint : carPlanCollectPointList1) {
                                    carPlanCollectPointIds.add(carPlanCollectPoint.getCollectPointId());
                                }
                                for (CarPlanCollectPoint carPlanCollectPoint : carPlanCollectPointList1) {
                                    TlFacilities tlFacilities = tlFacilitiesMap.get(carPlanCollectPoint.getCollectPointId());
                                    if (null != tlFacilities) {
                                        RptCarWorkFacility rptCarWorkFacility = new RptCarWorkFacility();
                                        rptCarWorkFacility.setId(StringUtils.uuid());
                                        rptCarWorkFacility.setRptCarWorkId(rptCarWork.getId());
                                        rptCarWorkFacility.setCollectPointId(tlFacilities.getId());
                                        rptCarWorkFacility.setFacilityName(tlFacilities.getFaclname());
                                        rptCarWorkFacility.setCarId(carId);
                                        rptCarWorkFacility.setWorkDate(rptCarWork.getWorkDate());
                                        String[] facAddr = tlFacilities.getFacladdr().split(",");

                                        String lng = facAddr[0];
                                        String lat = facAddr[1];
                                        rptCarWorkFacility.setLat(lat);
                                        rptCarWorkFacility.setLng(lng);
                                        rptCarWorkFacility.setWorkType(1);
                                        rptCarWorkFacility.setRadii(tlFacilities.getRadii());
                                        rptCarWorkFacilityMapper.insert(rptCarWorkFacility);
                                    }
                                }
                            }

                            if (!carPlanCollectPointIds.isEmpty()) {
                                rptCarWork.setSjdIds(String.join(",", carPlanCollectPointIds));
                                rptCarWork.setAllProgress(carPlanCollectPointIds.size());
                            }

                        } else if (rptCarWork.getWorkType() == 4) {

                            List<CarPlanCollectStand> carPlanCollectStandList1 = carPlanCollectStandMap.get(rptCarWork.getPlanId());
                            if (null != carPlanCollectStandList1) {
                                for (CarPlanCollectStand carPlanCollectStand : carPlanCollectStandList1) {
                                    TlFacilities tlFacilities = tlFacilitiesMap.get(carPlanCollectStand.getCollectStandId());
                                    if (null != tlFacilities) {
                                        RptCarWorkFacility rptCarWorkFacility = new RptCarWorkFacility();
                                        rptCarWorkFacility.setId(StringUtils.uuid());
                                        rptCarWorkFacility.setRptCarWorkId(rptCarWork.getId());
                                        rptCarWorkFacility.setCollectStandId(tlFacilities.getId());
                                        rptCarWorkFacility.setFacilityName(tlFacilities.getFaclname());
                                        rptCarWorkFacility.setCarId(carId);
                                        rptCarWorkFacility.setWorkDate(rptCarWork.getWorkDate());
                                        String[] facAddr = tlFacilities.getFacladdr().split(",");
                                        String lng = facAddr[0];
                                        String lat = facAddr[1];
                                        rptCarWorkFacility.setLat(lat);
                                        rptCarWorkFacility.setLng(lng);
                                        rptCarWorkFacility.setRadii(tlFacilities.getRadii());
                                        rptCarWorkFacility.setWorkType(2);
                                        rptCarWorkFacilityMapper.insert(rptCarWorkFacility);
                                    }
                                }
                            }
                            List<CarPlanProcessStand> carPlanProcessStandList1 = carPlanProcessStandMap.get(rptCarWork.getPlanId());
                            if (null != carPlanProcessStandList1) {
                                for (CarPlanProcessStand carPlanProcessStand : carPlanProcessStandList1) {
                                    TlFacilities tlFacilities = tlFacilitiesMap.get(carPlanProcessStand.getProcessStandId());
                                    if (null != tlFacilities) {
                                        RptCarWorkFacility rptCarWorkFacility = new RptCarWorkFacility();
                                        rptCarWorkFacility.setId(StringUtils.uuid());
                                        rptCarWorkFacility.setRptCarWorkId(rptCarWork.getId());
                                        rptCarWorkFacility.setProcessStandId(tlFacilities.getId());
                                        rptCarWorkFacility.setFacilityName(tlFacilities.getFaclname());
                                        rptCarWorkFacility.setCarId(carId);
                                        rptCarWorkFacility.setWorkDate(rptCarWork.getWorkDate());
                                        String[] facAddr = tlFacilities.getFacladdr().split(",");
                                        String lng = facAddr[0];
                                        String lat = facAddr[1];
                                        rptCarWorkFacility.setLat(lat);
                                        rptCarWorkFacility.setLng(lng);
                                        rptCarWorkFacility.setRadii(tlFacilities.getRadii());
                                        rptCarWorkFacility.setWorkType(3);
                                        rptCarWorkFacilityMapper.insert(rptCarWorkFacility);
                                    }
                                }
                            }
                        }
                        rptCarWorkMapper.insert(rptCarWork);

                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("ERROR", e);
                    }
                }
            }
        }
    }


    @Scheduled(cron = "0 0 23 * * ?")
    public void initEmployeeAttendance() {
        if (timed_task) {
            log.info("==================人员考勤-初始化=================start=");
            /** 人员考勤 **/
            QueryWrapper<TlEmployee> tlEmployeeQueryWrapper = new QueryWrapper<>();
            List<TlEmployee> tlEmployeeList = tlEmployeeMapper.selectList(tlEmployeeQueryWrapper);
            for (TlEmployee tlEmployee : tlEmployeeList) {
                tlEmployee.setAttendance(1);
                tlEmployee.setShiftStatus(1);
                tlEmployee.setOnguardstatus(1);
                tlEmployeeMapper.updateById(tlEmployee);
            }
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);

            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM");
            String calendarMonth = sdf2.format(date);

            QueryWrapper<EmpPlanDate> empPlanDateQueryWrapper = new QueryWrapper<>();
            empPlanDateQueryWrapper.lambda().ge(EmpPlanDate::getEndDate, calendarDate);
            empPlanDateQueryWrapper.lambda().le(EmpPlanDate::getStartDate, calendarDate);
            List<EmpPlanDate> empPlanDateList = empPlanDateMapper.selectList(empPlanDateQueryWrapper);

            List<EmpPlan> empPlanList = empPlanMapper.selectList(new QueryWrapper<>());
            Map<String, EmpPlan> empPlanMap = empPlanList.stream().collect(Collectors.groupingBy(EmpPlan::getId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));


            List<EmpPlanEmployee> empPlanEmployeeList = empPlanEmployeeMapper.selectList(new QueryWrapper<>());
            Map<String, List<EmpPlanEmployee>> empPlanEmployeeMap = empPlanEmployeeList.stream().collect(Collectors.groupingBy(EmpPlanEmployee::getPlanId));

            List<TlEmployee> tlEmployeeListOne = tlEmployeeMapper.selectList(new QueryWrapper<>());
            Map<String, TlEmployee> tlEmployeeMap = tlEmployeeListOne.stream().collect(Collectors.groupingBy(TlEmployee::getId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));


            List<WorkGroup> workGroupList = workGroupMapper.selectList(new QueryWrapper<>());
            Map<String, WorkGroup> workGroupMap = workGroupList.stream().collect(Collectors.groupingBy(WorkGroup::getWorkGroupId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));

            List<Grid> gridList = gridMapper.selectList(new QueryWrapper<Grid>().lambda().eq(Grid::getGridType, 0));
            Map<String, Grid> gridMap = gridList.stream().collect(Collectors.groupingBy(Grid::getGridId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));

            List<WorkRule> workRuleList = workRuleMapper.selectList(new QueryWrapper<>());
            Map<String, WorkRule> workRuleMap = workRuleList.stream().collect(Collectors.groupingBy(WorkRule::getWorkRuleId, Collectors.collectingAndThen(Collectors.toList(), values -> values.get(0))));

            for (EmpPlanDate empPlanDate : empPlanDateList) {

                List<EmpPlanEmployee> empPlanEmployeeList1 = empPlanEmployeeMap.get(empPlanDate.getPlanId());
                if (null != empPlanEmployeeList1) {
                    for (EmpPlanEmployee empPlanEmployee : empPlanEmployeeList1) {
                        WorkGroup workGroup = workGroupMap.get(empPlanDate.getWorkGroupId());
                        if (null != workGroup) {
                            //勤类型，固定班1，冬夏班2
                            Integer kaoqinType = workGroup.getKaoqinType();
                            //1:夏季,2:冬季
                            String season = DateUtils.getCurrentSeason(new Date());
                            String kaoqinIds = workGroup.getKaoqinIds();
                            if (StringUtils.isEmpty(kaoqinIds)) {
                                return;
                            }
                            List<WorkKaoqin> workKaoqinList = workKaoqinMapper.selectBatchIds(Arrays.asList(kaoqinIds.split(",")));
                            for (WorkKaoqin workKaoqin : workKaoqinList) {

//                                String workDate = DateUtil.format(new Date(), "yyyy-MM-dd");
                                //重复判断
                                QueryWrapper<RptEmployeeWork> rptEmployeeWrokWrapper = new QueryWrapper<>();
                                rptEmployeeWrokWrapper.lambda().eq(RptEmployeeWork::getEmployeeId, empPlanEmployee.getEmployeeId());
                                rptEmployeeWrokWrapper.lambda().eq(RptEmployeeWork::getPlanId, empPlanEmployee.getPlanId());
                                rptEmployeeWrokWrapper.lambda().eq(RptEmployeeWork::getWorkDate, calendarDate);
                                rptEmployeeWrokWrapper.lambda().eq(RptEmployeeWork::getShiftId, workKaoqin.getWorkKaoqinId());
                                List<RptEmployeeWork> rptEmployeeWorkList = rptEmployeeWorkMapper.selectList(rptEmployeeWrokWrapper);
                                if (!CollectionUtils.isEmpty(rptEmployeeWorkList)) {
                                    continue;
                                }
                                String planStartTime = null;//排班开始时间
                                String planEndTime = null;//排班结束时间
                                if (1 == kaoqinType) {//固定班
                                    planStartTime = workKaoqin.getSbsj();
                                    planEndTime = workKaoqin.getXbsj();
                                } else if (2 == kaoqinType) {//冬夏班
                                    if ("summer".equals(season)) {
                                        planStartTime = workKaoqin.getXsbsj();
                                        planEndTime = workKaoqin.getXxbsj();
                                    } else if ("winter".equals(season)) {
                                        planStartTime = workKaoqin.getDsbsj();
                                        planEndTime = workKaoqin.getDxbsj();
                                    }
                                }
                                RptEmployeeWork rptEmployeeWork = new RptEmployeeWork();
                                rptEmployeeWork.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                                rptEmployeeWork.setEmployeeId(empPlanEmployee.getEmployeeId());
                                TlEmployee tlEmployee = tlEmployeeMap.get(empPlanEmployee.getEmployeeId());
                                if (null != tlEmployee) {
                                    tlEmployee.setShiftStatus(0);
                                    tlEmployeeMapper.updateById(tlEmployee);

                                    rptEmployeeWork.setEmployeeName(tlEmployee.getName());
                                }
                                EmpPlan empPlan = empPlanMap.get(empPlanDate.getPlanId());
                                if (null != empPlan) {
                                    rptEmployeeWork.setPlanId(empPlan.getId());
                                    rptEmployeeWork.setPlanName(empPlan.getPlanName());
                                    rptEmployeeWork.setGridId(empPlan.getGridId());
                                    rptEmployeeWork.setDepId(empPlan.getDepartmentId());
                                    Grid grid = gridMap.get(empPlan.getGridId());
                                    if (null != grid) {
                                        rptEmployeeWork.setGridName(grid.getName());
                                        if (null != grid.getKm()) {
                                            rptEmployeeWork.setAllProgress(grid.getKm().intValue());
                                        }
                                    }
                                    WorkRule workRule = workRuleMap.get(empPlan.getWorkRuleId());
                                    if (null != workRule) {
                                        rptEmployeeWork.setRuleId(workRule.getWorkRuleId());
                                        rptEmployeeWork.setRuleName(null == workRule.getRuleName() ? "" : workRule.getRuleName());
                                    }
                                }
                                rptEmployeeWork.setGroupId(workGroup.getWorkGroupId());
                                rptEmployeeWork.setGroupName(workGroup.getName());
                                rptEmployeeWork.setWorkDate(calendarDate);
                                rptEmployeeWork.setWorkMonth(calendarMonth);
                                rptEmployeeWork.setPlanStartTime(DateUtil.parse(calendarDate + planStartTime, "yyyy-MM-ddHH:mm"));
                                rptEmployeeWork.setPlanEndTime(DateUtil.parse(calendarDate + planEndTime, "yyyy-MM-ddHH:mm"));
                                rptEmployeeWork.setCreateTime(new Date());
                                rptEmployeeWork.setShiftId(workKaoqin.getWorkKaoqinId());
                                rptEmployeeWork.setShiftName(workKaoqin.getName());
                                rptEmployeeWorkMapper.insert(rptEmployeeWork);
                            }
                        }

                    }
                }

            }
        }
        log.info("==================人员考勤-初始化=================end=");
    }

    /**
     * 生成电子围栏第二天的考勤打卡记录
     */
    @Scheduled(cron = "0 30 23 * * ?")
    public void generateAttendanceRecords() {
        if (timed_task) {
            //在职人员
            QueryWrapper<TlEmployee> tlEmployeeQueryWrapper = new QueryWrapper<>();
            tlEmployeeQueryWrapper.lambda().eq(TlEmployee::getStatus, Constants.EMPLOYEE_STATUS_INCUMBENT);
            List<TlEmployee> tlEmployees = tlEmployeeMapper.selectList(tlEmployeeQueryWrapper);

            //部门
            Map<String, SysDepart> sysDepartMap = sysDepartService.getDepartMap(new QueryWrapper<>());

            //电子围栏
            QueryWrapper<Grid> gridQueryWrapper = new QueryWrapper<>();
            gridQueryWrapper.lambda().eq(Grid::getIsEnable, Constants.ENABLED_STATE_ENABLE);
            List<Grid> grids = gridMapper.selectList(gridQueryWrapper);
            Map<String, Grid> gridMap = grids.stream().collect(Collectors.groupingBy(Grid::getGridId, Collectors.collectingAndThen(Collectors.toList(), a -> a.get(0))));

            //电子围栏考勤段表
            List<GridCheckwork> gridCheckworks = gridCheckworkMapper.selectList(new QueryWrapper<>());
            Map<String, List<GridCheckwork>> gridCheckworkListMap = gridCheckworks.stream().collect(Collectors.groupingBy(GridCheckwork::getGridId, toList()));

            //在职人员所属电子围栏
            QueryWrapper<GridBind> gridBindQueryWrapper = new QueryWrapper<>();
            gridBindQueryWrapper.lambda().eq(GridBind::getType, Constants.TYPE_PERSON);
            List<GridBind> gridBinds = gridBindMapper.selectList(gridBindQueryWrapper);
            Map<String, List<GridBind>> gridBindListMap = gridBinds.stream().collect(Collectors.groupingBy(GridBind::getItemId, toList()));

            //遍历在职人员
            tlEmployees.forEach(t->{
                //获取该人员绑定电子围栏信息
                List<GridBind> gridBindsList = gridBindListMap.get(t.getId());
                if (Objects.nonNull(gridBindsList) && gridBindsList.size() > 0){
                    //遍历绑定的电子围栏
                    gridBindsList.forEach(j->{
                        //获取电子围栏id
                        String gridId = j.getGridId();
                        //获取电子围栏
                        Grid grid = gridMap.get(gridId);
                        if (Objects.nonNull(grid)){
                            //获取该电子围栏的考勤时间段信息
                            List<GridCheckwork> gridCheckworksList = gridCheckworkListMap.get(gridId);
                            if (Objects.nonNull(gridCheckworksList) && gridCheckworksList.size() > 0){
                                //遍历电子围栏考勤时间段
                                gridCheckworksList.forEach(k->{
                                    //生成该人员第二天规定的打卡记录
                                    EmployeePunchCard employeePunchCard = new EmployeePunchCard();
                                    employeePunchCard.setEmployeeId(t.getId());
                                    employeePunchCard.setEmployeeName(t.getName());
                                    employeePunchCard.setDepartmentId(t.getEmpldeptid());
                                    SysDepart sysDepart = sysDepartMap.get(t.getEmpldeptid());
                                    if (null != sysDepart) {
                                        employeePunchCard.setDepartmentName(sysDepart.getDepartName());
                                    }
                                    employeePunchCard.setPunchCardDate(DateUtil.formatDate(DateUtil.tomorrow()));
                                    employeePunchCard.setPunchCardMonth(DateUtil.format(DateUtil.tomorrow(), "yyyy-MM"));

                                    //0是固定班 1是夏季班 2是冬季班
                                    if (Constants.SHIFT_TYPE_FIXED_CLASS == k.getType()){
                                        employeePunchCard.setWorkTime(k.getStartTime() + ":00");
                                        employeePunchCard.setAfterWorkTime(k.getEndTime() + ":00");
                                    } else {
                                        String season = DateUtils.getCurrentSeason(new Date());
                                        if ("summer".equals(season) && Constants.SHIFT_TYPE_SUMMER_CLASS == k.getType()) {
                                            employeePunchCard.setWorkTime(k.getStartTime() + ":00");
                                            employeePunchCard.setAfterWorkTime(k.getEndTime() + ":00");
                                        } else if ("winter".equals(season) && Constants.SHIFT_TYPE_WINTER_CLASS == k.getType()) {
                                            employeePunchCard.setWorkTime(k.getStartTime() + ":00");
                                            employeePunchCard.setAfterWorkTime(k.getEndTime() + ":00");
                                        } else {
                                            return;
                                        }
                                    }

                                    employeePunchCard.setStartWorkPunchCardProvision(grid.getStartWorkPunchCard());
                                    employeePunchCard.setEndWorkPunchCardProvision(grid.getEndWorkPunchCard());
                                    employeePunchCard.setLaterInProvision(grid.getLaterIn());
                                    employeePunchCard.setLeaveEarlyProvision(grid.getLeaveEarly());
                                    employeePunchCard.setNoWorkProvision(grid.getNoWork());
                                    employeePunchCard.setType(0);
                                    employeePunchCard.setGridId(k.getGridId());
                                    employeePunchCard.setManCarType(Constants.TYPE_PERSON);
                                    employeePunchCard.setCreatTime(new Date());
                                    employeePunchCardMapper.insert(employeePunchCard);
                                });
                            }
                        }
                    });
                }
            });
        }
    }


    /**
     *  人员上班自动打卡
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void automaticPunchCardForStaffToWork() {
        if (timed_task) {
            //当前时间
            Date dayTime = new Date();
            //当前日期
            String day = DateUtil.formatDate(new Date());
            //筛选出当天规定打卡的人
            List<String> employeeIds = new ArrayList<>();
            //筛选出当天规定打卡的电子围栏
            List<String> gridIds = new ArrayList<>();

            //查询当天需要打上班卡的数据
            QueryWrapper<EmployeePunchCard> objectQueryWrapper = new QueryWrapper<>();
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getPunchCardDate, DateUtil.today());
            objectQueryWrapper.lambda().isNull(EmployeePunchCard::getActualWorkTime);
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getLackCard,Constants.STATE_NORMAL);
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getManCarType, Constants.TYPE_PERSON);
            List<EmployeePunchCard> employeePunchCards = employeePunchCardMapper.selectList(objectQueryWrapper);
            employeePunchCards.forEach(t->{
                employeeIds.add(t.getEmployeeId());
                gridIds.add(t.getGridId());
            });

            if (employeeIds.size() == 0 || gridIds.size() == 0){
                return;
            }

            //十分钟内的人员轨迹数据
            QueryWrapper<EmployeeTrack> employeeTrackQueryWrapper = new QueryWrapper<>();
            employeeTrackQueryWrapper.lambda().in(EmployeeTrack::getEmployeeId, employeeIds);
            employeeTrackQueryWrapper.lambda().between(EmployeeTrack::getTimestamp, DateUtils.getpostponetimesoradvancetimesByMinute(new Date(), 11), new Date());
            List<EmployeeTrack> employeeTracks = employeeTrackMapper.selectList(employeeTrackQueryWrapper);
            Map<String, List<EmployeeTrack>> employeeTracksMapByEmployeeId = employeeTracks.stream().filter(a -> StringUtils.isNotEmpty(a.getEmployeeId())).collect(Collectors.groupingBy(EmployeeTrack::getEmployeeId, toList()));

            //电子围栏
            QueryWrapper<GridSnapshot> gridQueryWrapper = new QueryWrapper<>();
            gridQueryWrapper.lambda().in(GridSnapshot::getGridId, gridIds);
            gridQueryWrapper.lambda().eq(GridSnapshot::getDate, day);
            gridQueryWrapper.lambda().eq(GridSnapshot::getIsEnable, Constants.ENABLED_STATE_ENABLE);
            List<GridSnapshot> grids = gridSnapshotMapper.selectList(gridQueryWrapper);
            Map<String, GridSnapshot> gridMap = grids.stream().collect(Collectors.groupingBy(GridSnapshot::getGridId, Collectors.collectingAndThen(Collectors.toList(), a -> a.get(0))));

            //遍历需要打卡的数据
            employeePunchCards.forEach(t->{
                //该人员十分钟内的轨迹数据
                List<EmployeeTrack> employeeTrackList = employeeTracksMapByEmployeeId.get(t.getEmployeeId());
                if (Objects.nonNull(employeeTrackList)){
                    //按照时间正序排序
                    Collections.sort(employeeTrackList, (o1, o2) -> {
                        Date d1 = o1.getTimestamp();
                        Date d2 = o2.getTimestamp();
                        return d1.compareTo(d2);
                    });
                    //进电子围栏的最早上班打卡时间
                    Date actualWorkTime = null;
                    for (EmployeeTrack k:
                            employeeTrackList) {
                        //(轨迹时间晚于允许提前打卡规定时间, 并且早于下班打卡时间)
                        if (k.getTimestamp().compareTo(DateUtils.getpostponetimesoradvancetimesByMinute(DateUtil.parseDateTime(day + " " + t.getWorkTime()), t.getStartWorkPunchCardProvision())) >= 0 && k.getTimestamp().compareTo(DateUtil.parseDateTime(day + " " + t.getAfterWorkTime())) <= 0){
                            GridSnapshot grid = gridMap.get(t.getGridId());
                            if (Objects.nonNull(grid)){
                                //判断是不是在电子围栏内
                                boolean isItInTheElectronicGrid = DistanceUtils.insideGrid(Double.valueOf(k.getLng()), Double.valueOf(k.getLat()), grid);
                                if (isItInTheElectronicGrid){
                                    actualWorkTime = k.getTimestamp();
                                    break;
                                }
                            }
                        }
                    }
                    //进电子围栏的最早上班打卡时间不为空 则为正常打上班卡
                    if (Objects.nonNull(actualWorkTime)){
                        t.setActualWorkTime(DateUtil.formatTime(actualWorkTime));
                        // 打卡时间晚于迟到规定时间 视为迟到
                        if (actualWorkTime.compareTo(DateUtils.getpostponetimesoradvancetimesByMinute(DateUtil.parseDateTime(day + " " + t.getWorkTime()), t.getLaterInProvision())) > 0){
                            t.setLaterIn(Constants.STATE_ABNORMAL);
                        }
                        employeePunchCardMapper.updateById(t);
                    }

                    //当前时间过允许延后打卡规定的下班时间 实际上班打卡时间为空的数据 更新为缺卡和旷工
                    if (dayTime.compareTo(DateUtils.getpostponetimesoradvancetimesByMinute(DateUtil.parseDateTime(day + " " + t.getAfterWorkTime()), -t.getEndWorkPunchCardProvision())) > 0
                            && StringUtils.isEmpty(t.getActualWorkTime()) && Constants.STATE_NORMAL == t.getLackCard()){
                        t.setLackCard(Constants.STATE_ABNORMAL);
                        t.setNoWork(Constants.STATE_ABNORMAL);
                        employeePunchCardMapper.updateById(t);
                    }
                }
            });
        }
    }

    /**
     *  人员下班自动打卡
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void automaticPunchCardForStaffAfterGetOffWork() {
        if (timed_task) {
            //当前时间
            Date dayTime = new Date();
            //当前日期
            String day = DateUtil.formatDate(new Date());
            //筛选出当天规定打卡的人
            List<String> employeeIds = new ArrayList<>();
            //筛选出当天规定打卡的电子围栏
            List<String> gridIds = new ArrayList<>();

            //查询当天需要打上班卡的数据
            QueryWrapper<EmployeePunchCard> objectQueryWrapper = new QueryWrapper<>();
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getPunchCardDate, DateUtil.today());
            objectQueryWrapper.lambda().isNotNull(EmployeePunchCard::getActualWorkTime);
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getLackCard,Constants.STATE_NORMAL);
            objectQueryWrapper.lambda().eq(EmployeePunchCard::getManCarType, Constants.TYPE_PERSON);
            List<EmployeePunchCard> employeePunchCards = employeePunchCardMapper.selectList(objectQueryWrapper);
            employeePunchCards.forEach(t->{
                employeeIds.add(t.getEmployeeId());
                gridIds.add(t.getGridId());
            });

            if (employeeIds.size() == 0 || gridIds.size() == 0){
                return;
            }

            //十分钟内的人员轨迹数据
            QueryWrapper<EmployeeTrack> employeeTrackQueryWrapper = new QueryWrapper<>();
            employeeTrackQueryWrapper.lambda().in(EmployeeTrack::getEmployeeId, employeeIds);
            employeeTrackQueryWrapper.lambda().between(EmployeeTrack::getTimestamp, DateUtils.getpostponetimesoradvancetimesByMinute(new Date(), 11), new Date());
            List<EmployeeTrack> employeeTracks = employeeTrackMapper.selectList(employeeTrackQueryWrapper);
            Map<String, List<EmployeeTrack>> employeeTracksMapByEmployeeId = employeeTracks.stream().filter(a -> StringUtils.isNotEmpty(a.getEmployeeId())).collect(Collectors.groupingBy(EmployeeTrack::getEmployeeId, toList()));

            //电子围栏
            QueryWrapper<GridSnapshot> gridQueryWrapper = new QueryWrapper<>();
            gridQueryWrapper.lambda().in(GridSnapshot::getGridId, gridIds);
            gridQueryWrapper.lambda().eq(GridSnapshot::getDate, day);
            gridQueryWrapper.lambda().eq(GridSnapshot::getIsEnable, Constants.ENABLED_STATE_ENABLE);
            List<GridSnapshot> grids = gridSnapshotMapper.selectList(gridQueryWrapper);
            Map<String, GridSnapshot> gridMap = grids.stream().collect(Collectors.groupingBy(GridSnapshot::getGridId, Collectors.collectingAndThen(Collectors.toList(), a -> a.get(0))));

            //遍历需要打卡的数据
            employeePunchCards.forEach(t->{
                //该人员十分钟内的轨迹数据
                List<EmployeeTrack> employeeTrackList = employeeTracksMapByEmployeeId.get(t.getEmployeeId());
                if (Objects.nonNull(employeeTrackList)){
                    //按照时间倒序
                    Collections.sort(employeeTrackList, (o1, o2) -> {
                        Date d1 = o1.getTimestamp();
                        Date d2 = o2.getTimestamp();
                        return d2.compareTo(d1);
                    });
                    for (EmployeeTrack k:
                            employeeTrackList) {
                        //(轨迹时间晚于上班时间 且早于允许延后打卡规定时间)
                        if (k.getTimestamp().compareTo(DateUtil.parseDateTime(day + " " + t.getWorkTime())) >= 0 && k.getTimestamp().compareTo(DateUtils.getpostponetimesoradvancetimesByMinute(DateUtil.parseDateTime(day + " " + t.getAfterWorkTime()), -t.getEndWorkPunchCardProvision())) <= 0){
                            GridSnapshot grid = gridMap.get(t.getGridId());
                            if (Objects.nonNull(grid)){
                                //判断是不是在电子围栏内
                                boolean isItInTheElectronicGrid = DistanceUtils.insideGrid(Double.valueOf(k.getLng()), Double.valueOf(k.getLat()), grid);
                                if (isItInTheElectronicGrid){
                                    //更新Redis的下班打卡时间
                                    RedisUtil.set(EndWorkPunchCardTimeKey.token, t.getEmployeeId(), k.getTimestamp());
                                    break;
                                }
                            }
                        }
                    }

                    //当前时间过允许延后打卡规定的下班时间
                    if (dayTime.compareTo(DateUtils.getpostponetimesoradvancetimesByMinute(DateUtil.parseDateTime(day + " " + t.getAfterWorkTime()), -t.getEndWorkPunchCardProvision())) > 0
                            && Constants.STATE_NORMAL == t.getLackCard()){
                        //从Redis获取下班打卡时间
                        Date date = RedisUtil.get(EndWorkPunchCardTimeKey.token, t.getEmployeeId(), Date.class);
                        if (Objects.nonNull(date)){
                            t.setActualAfterWorkTime(DateUtil.formatTime(date));
                        } else { //没有下班打卡时间 视为缺卡 旷工
                            t.setLackCard(Constants.STATE_ABNORMAL);
                            t.setNoWork(Constants.STATE_ABNORMAL);
                            employeePunchCardMapper.updateById(t);
                        }
                        //规定上班时长(分钟)
                        long specifiedDuration = DateUtil.between(DateUtil.parseDateTime(day + " " + t.getWorkTime()), DateUtil.parseDateTime(day + " " + t.getAfterWorkTime()), MINUTE);
                        //实际上班时长(分钟)
                        long actualDuration = DateUtil.between(DateUtil.parseDateTime(day + " " + t.getActualWorkTime()), date, MINUTE);
                        //规定上班时长比实际上班时长 大于旷工规定的时长 更新为旷工
                        if ((specifiedDuration - actualDuration) > t.getNoWorkProvision()){
                            t.setNoWork(Constants.STATE_ABNORMAL);
                            employeePunchCardMapper.updateById(t);
                        }
                    }
                }
            });
        }
    }

    @Scheduled(cron = "0 0 22 * * ?")
    public void copyGrid() {
        if (timed_task) {
            /** 复刻网格信息 **/
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);

            QueryWrapper<Grid> gridQueryWrapper = new QueryWrapper<>();
            List<Grid> gridList = gridMapper.selectList(gridQueryWrapper);
            List<GridSnapshot> gridSnapshotList = new ArrayList<>();
            gridList.forEach(grid -> {
                System.out.println("网格复刻开始: =======================");
                GridSnapshot gridSnapshot = new GridSnapshot();
                gridSnapshot.setId(StringUtils.uuid());
                gridSnapshot.setDate(calendarDate);
                BeanUtils.copyProperties(grid, gridSnapshot);
                gridSnapshot.setCreateTime(new Date());
                gridSnapshot.setUpdateTime(new Date());
                gridSnapshotList.add(gridSnapshot);
                System.out.println("网格复刻结束: =======================");
            });
            gridSnapshotService.saveBatch(gridSnapshotList);
            gridService.initEmpWorkPointsList(date, gridList);
        }
    }

    @Scheduled(cron = "0 0 22 * * ?")
    public void copyGridBind() {
        if (timed_task) {
            /** 复刻网格信息 **/
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);

            System.out.println("电子围栏绑定信息复刻开始: =======================");
            List<GridBindSnapshot> gridBindSnapshotList = new ArrayList<>();
            QueryWrapper<GridBind> gridBindQueryWrapper = new QueryWrapper<>();
            List<GridBind> gridBindList = gridBindMapper.selectList(gridBindQueryWrapper);
            for (GridBind gridBind : gridBindList) {
                GridBindSnapshot gridBindSnapshot = new GridBindSnapshot();
                BeanUtils.copyProperties(gridBind, gridBindSnapshot);
                gridBindSnapshot.setId(StringUtils.uuid());
                gridBindSnapshot.setDate(calendarDate);
                gridBindSnapshotList.add(gridBindSnapshot);
//                gridBindSnapshotMapper.insert(gridBindSnapshot);
            }
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(gridBindSnapshotList)){
                gridBindSnapshotService.saveBatch(gridBindSnapshotList);
            }
            System.out.println("电子围栏绑定信息复刻结束: =======================");
        }
    }

    @Scheduled(cron = "0 0 22 * * ?")
    public void copyGridCheckWork() {
        if (timed_task) {
            /** 复刻网格信息 **/
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);


            System.out.println("电子围栏考勤段复刻开始: =======================");
            List<GridCheckworkSnapshot> gridCheckworkSnapshotList = new ArrayList<>();
            List<GridCheckwork> gridCheckworkList = gridCheckWorkMapper.selectList(new QueryWrapper<>());
            for (GridCheckwork gridCheckwork : gridCheckworkList) {
                GridCheckworkSnapshot gridCheckWorkSnapshot = new GridCheckworkSnapshot();
                BeanUtils.copyProperties(gridCheckwork, gridCheckWorkSnapshot);
                gridCheckWorkSnapshot.setId(StringUtils.uuid());
                gridCheckWorkSnapshot.setDate(calendarDate);
                gridCheckWorkSnapshot.setCreatTime(new Date());
                gridCheckWorkSnapshot.setUpdateTime(new Date());
                gridCheckworkSnapshotList.add(gridCheckWorkSnapshot);
//                gridCheckWorkSnapshotMapper.insert(gridCheckWorkSnapshot);
            }
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(gridCheckworkSnapshotList)){
                gridCheckWorkSnapshotService.saveBatch(gridCheckworkSnapshotList);
            }
            System.out.println("电子围栏考勤段复刻结束: =======================");
        }
    }

    @Scheduled(cron = "0 0 22 * * ?")
    public void copyGridBindCheckWork() throws ParseException {
        if (timed_task) {
            /** 复刻网格信息 **/
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            Integer year = c.get(Calendar.YEAR);
            String newYear = year.toString();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);

            QueryWrapper<GridBind> gridBindQueryWrapper = new QueryWrapper<>();
            List<GridBind> gridBindList = gridBindMapper.selectList(gridBindQueryWrapper);

            QueryWrapper<GridCheckwork> gridCheckworkQueryWrapper = new QueryWrapper<>();
            if (calendarDate.compareTo(newYear + "-05-01") < 0 || calendarDate.compareTo(newYear + "-10-01") >= 0) {
                gridCheckworkQueryWrapper.lambda().eq(GridCheckwork::getType, 2);
                gridCheckworkQueryWrapper.lambda().or().eq(GridCheckwork::getType, 0);
            } else {
                gridCheckworkQueryWrapper.lambda().eq(GridCheckwork::getType, 1);
                gridCheckworkQueryWrapper.lambda().or().eq(GridCheckwork::getType, 0);
            }
            List<GridCheckwork> gridCheckworkList = gridCheckWorkMapper.selectList(gridCheckworkQueryWrapper);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            List<GridBindCheckwork> gridBindCheckworkList = new ArrayList<>();


            System.out.println("每日考勤表导入开始: =======================");
            for (GridBind gridBind : gridBindList) {
                for (GridCheckwork gridCheckwork : gridCheckworkList) {
                    if (gridBind.getGridId().equals(gridCheckwork.getGridId())) {
                        GridBindCheckwork gridBindCheckWork = new GridBindCheckwork();
                        gridBindCheckWork.setGridId(gridBind.getGridId());
                        gridBindCheckWork.setGridName(gridBind.getGridName());
                        gridBindCheckWork.setType(gridBind.getType());
                        gridBindCheckWork.setItemId(gridBind.getItemId());
                        gridBindCheckWork.setBindTime(gridBind.getBindTime());
                        gridBindCheckWork.setCheckWorkName(gridCheckwork.getCheckWorkName());
                        gridBindCheckWork.setDate(calendarDate);
                        gridBindCheckWork.setStartTimeString(calendarDate + " " + gridCheckwork.getStartTime() + ":00");
                        gridBindCheckWork.setEndTimeString(calendarDate + " " + gridCheckwork.getEndTime() + ":00");
                        gridBindCheckWork.setStartTime(sdf.parse(gridBindCheckWork.getStartTimeString()));
                        gridBindCheckWork.setEndTime(sdf.parse(gridBindCheckWork.getEndTimeString()));
                        gridBindCheckworkList.add(gridBindCheckWork);
                    }
                }
            }
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(gridBindCheckworkList)) {
                gridBindCheckWorkService.saveBatch(gridBindCheckworkList);
            }
            System.out.println("每日考勤表导入结束: =======================");
        }
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void updateTimeConsumingInTheMorning() {
        if (timed_task) {
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, -1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);
            carPlanService.updateRptCarWorkByTimeConsuming(calendarDate);
        }
    }

    @Scheduled(cron = "0 7/10 * * * ?")
    public void updateTimeConsuming() {
        if (timed_task) {
            String date = StringUtils.dateToStr(new Date(), "yyyy-MM-dd");
            carPlanService.updateRptCarWorkByTimeConsuming(date);
        }
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void updateCleanTypeInTheMorning() {
        if (timed_task) {
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, -1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);
            carPlanService.updateCleanType(calendarDate);
        }
    }

    @Scheduled(cron = "0 7/10 * * * ?")
    public void updateCleanType() {
        if (timed_task) {
            String date = StringUtils.dateToStr(new Date(), "yyyy-MM-dd");
            carPlanService.updateCleanType(date);
        }
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void updateTrashPickupWorkInTheMorning() {
        if (timed_task) {
            Date date = new Date();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_MONTH, -1);
            date = c.getTime();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String calendarDate = sdf1.format(date);
            carPlanService.updateTrashPickupWork(calendarDate);
        }
    }

//    @Scheduled(cron = "0 8/10 * * * ?")
//    public void updateTrashPickupWork() {
//        if (timed_task) {
//            String date = StringUtils.dateToStr(new Date(), "yyyy-MM-dd");
//            carPlanService.updateTrashPickupWork(date);
//        }
//    }


    /**
     * 判断案件是否逾期
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    private void caseOverdue() {
        if (timed_task) {
            try {
                QueryWrapper<Cases> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(Cases::getStatus, 2);
                queryWrapper.lambda().eq(Cases::getIsArchive, 0);
                List<Cases> casesList = casesMapper.selectList(queryWrapper);
                List<Cases> odList = new ArrayList<>();
                for (Cases cases : casesList) {
                    QueryWrapper<CaseProcess> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.lambda().orderByDesc(CaseProcess::getCreateTime);
                    List<String> status = new ArrayList<>();
                    status.add("创建");
                    status.add("分派");
                    status.add("改派");
                    queryWrapper1.lambda().in(CaseProcess::getHandle, status);
                    queryWrapper1.lambda().eq(CaseProcess::getCaseId, cases.getCaseId());
                    queryWrapper1.lambda().last("limit 1");
                    List<CaseProcess> caseProcessList = caseProcessMapper.selectList(queryWrapper1);
                    if (StringUtils.isNotEmpty(caseProcessList) && caseProcessList.size() > 0 && StringUtils.isNotEmpty(caseProcessList.get(0).getCreateTime())) {
                        Date date = caseProcessList.get(0).getCreateTime();
                        Long consumingTime = System.currentTimeMillis() - date.getTime();
                        Cases c = new Cases();
                        c.setCaseId(cases.getCaseId());
                        if (consumingTime != null && consumingTime >= 0) {
                            c.setConsumingTime(StringUtils.s2date(consumingTime / 1000));
                        } else {
                            c.setConsumingTime(StringUtils.s2date(0L));
                        }
                        long overdue = (consumingTime - cases.getTimelimit() * 60 * 1000) / 1000;
                        if (overdue >= 0) {
                            c.setIsOverdue(1);
                            c.setOverdueTime(StringUtils.s2date(overdue));
                        }
                        odList.add(c);
                    }
                }
                if (odList.size() > 0) {
                    casesService.updateBatchById(odList);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

//    /**
//     * 作业管理-机械作业-里程完成度分析
//     */
//    @Scheduled(cron = "0 3/10 * * * ?")
//    private void mileageCompleteness() {
//        if (timed_task) {
//            String today = StringUtils.dateToStr(new Date(), "yyyy-MM-dd");
//            // 里程完成率阈值
//            Jobset jobset = jobsetMapper.selectById(3);
//            Double kot = (StringUtils.isNotEmpty(jobset) && StringUtils.isNotEmpty(jobset.getKmOkThreshold())) ? jobset.getKmOkThreshold() : 1.0;
//            QueryWrapper<JxqsPlan> queryWrapper = new QueryWrapper<>();
//            queryWrapper.lambda().le(JxqsPlan::getYxsdStart, today);
//            queryWrapper.lambda().ge(JxqsPlan::getYxsdEnd, today);
//            List<JxqsPlan> plans = jxqsPlanService.list(queryWrapper);
//            for (JxqsPlan plan : plans) {
//                if (StringUtils.isNotEmpty(plan.getCarIds()) && StringUtils.isNotEmpty(plan.getType()) && StringUtils.isNotEmpty(plan.getGridId())) {
//                    Grid grid = gridService.getById(plan.getGridId());
//                    if (StringUtils.isEmpty(grid)) {
//                        continue;
//                    }
//                    Double planKm = grid.getKm();
//                    if (StringUtils.isNotEmpty(planKm)) {
//                        if (plan.getType() == 1) { //固定作业
//                            String carId = plan.getCarIds();
//                            // TODO: 2021/7/7 优化：只计算增量数据
//                            QueryWrapper<KfkCarLocation> kfkCarLocationQueryWrapper = new QueryWrapper<>();
//                            kfkCarLocationQueryWrapper.lambda().ge(KfkCarLocation::getDeviceTime, today);
//                            kfkCarLocationQueryWrapper.lambda().eq(KfkCarLocation::getCarid, carId);
//                            List<KfkCarLocation> kfkCarLocations = kfkCarLocationService.list(kfkCarLocationQueryWrapper);
//                            // TODO: 2021/7/7 在作业班组时间段内才算有效作业
//
//                            Double workKm = 0.0;
//                            Double runKm = 0.0;
//                            Date startTime = null;
//                            if (kfkCarLocations.size() > 0) {
//                                runKm = kfkCarLocations.get(kfkCarLocations.size() - 1).getMileage() - kfkCarLocations.get(0).getMileage();
//                                List<KfkCarLocation> kfkCarLocations1 = kfkCarLocations.stream().filter(kfkCarLocation -> "1".equals(kfkCarLocation.getStatus())).collect(Collectors.toList());
//                                if (kfkCarLocations1.size() > 0) {
//                                    startTime = kfkCarLocations1.get(0).getDeviceTime();
//                                    Double mileageTemp = kfkCarLocations1.get(0).getMileage();
//                                    for (int i = 0; i < kfkCarLocations.size(); i++) {
//                                        if (i % 10 == 0) {
//                                            if (StringUtils.isNotEmpty(kfkCarLocations.get(i).getMileage()) && StringUtils.isNotEmpty(kfkCarLocations.get(i).getStatus())) {
//                                                if ("1".equals(kfkCarLocations.get(i).getStatus()) && StringUtils.isNotEmpty(grid.getType())) {
//                                                    // 在网格内才算有效作业
//                                                    boolean inside = false;
//                                                    if (grid.getType() == 1) {
//                                                        if (grid.getAreaType() == 3) { // 圆形区域
//                                                            inside = DistanceUtils.insideCircle(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), Double.valueOf(grid.getLng()),
//                                                                    Double.valueOf(grid.getLat()), grid.getRadius());
//                                                        } else if (grid.getAreaType() == 4) { // 矩形
//                                                            inside = DistanceUtils.insideRect(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                                        } else if (grid.getAreaType() == 5) { // 多边形区域
//                                                            inside = DistanceUtils.insidePolygon(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                                        }
//                                                    } else if (grid.getType() == 2) { // 线路
//                                                        if (StringUtils.isNotEmpty(grid.getSectionIds())) {
//                                                            String[] sectionIds = grid.getSectionIds().split(",");
//                                                            QueryWrapper<Grid> queryWrapper1 = new QueryWrapper<>();
//                                                            queryWrapper1.lambda().in(Grid::getGridId, Arrays.asList(sectionIds));
//                                                            queryWrapper1.lambda().eq(Grid::getType, 3);
//                                                            List<Grid> grids = gridService.list(queryWrapper1);
//                                                            for (Grid g : grids) {
//                                                                log.info("==判断坐标是否网格内(mileageCompleteness)线路-1,gridId:{}", g.getGridId());
//                                                                inside = DistanceUtils.insideLine(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                                        Double.valueOf(kfkCarLocations.get(i).getLat()), g.getLnglat());
//                                                                if (inside) {
//                                                                    break;
//                                                                }
//                                                            }
//                                                        }
//                                                    } else if (grid.getType() == 3) { // 路段
//                                                        log.info("==判断坐标是否网格内(mileageCompleteness)路段-2,gridId:{}", grid.getGridId());
//                                                        inside = DistanceUtils.insideLine(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                                Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                                    }
//
//                                                    if (inside) {
//                                                        workKm += kfkCarLocations.get(i).getMileage() - mileageTemp;
//                                                    }
//                                                }
//                                                mileageTemp = kfkCarLocations.get(i).getMileage();
//                                            }
//                                        }
//                                    }
//                                }
//                            }
//                            JxqsWorkCarDetail jxqsWorkCarDetail = new JxqsWorkCarDetail();
//                            jxqsWorkCarDetail.setCarId(carId);
//                            jxqsWorkCarDetail.setCarName(plan.getCarNames());
//                            jxqsWorkCarDetail.setKmFinishRate((int) (workKm * 100 / planKm));
//                            jxqsWorkCarDetail.setPlanKm(planKm);
//                            jxqsWorkCarDetail.setRunKm(runKm);
//                            jxqsWorkCarDetail.setWorkKm(workKm);
//                            jxqsWorkCarDetail.setInvalidKm(runKm - workKm);
//                            jxqsWorkCarDetail.setCarStartTime(startTime);
//                            jxqsWorkCarDetail.setFunType(1);
//                            jxqsWorkCarDetail.setWorkDate(LocalDate.now());
//                            jxqsWorkCarDetail.setPlanId(plan.getJxqsPlanId());
//                            jxqsWorkCarDetail.setPlanName(plan.getName());
//                            jxqsWorkCarDetail.setDepId(grid.getDepid());
//                            jxqsWorkCarDetail.setDepName(grid.getDepName());
//                            jxqsWorkCarDetail.setWorkCycle(plan.getWorkPeriod());
//                            jxqsWorkCarDetail.setStatus(workKm > planKm * kot ? 1 : 0);
//                            QueryWrapper<CarViolation> carViolationQueryWrapper = new QueryWrapper<>();
//                            carViolationQueryWrapper.lambda().eq(CarViolation::getCarId, carId);
//                            carViolationQueryWrapper.lambda().like(CarViolation::getTime, today);
//                            carViolationQueryWrapper.lambda().eq(CarViolation::getModule, 3);
//                            int vc = carViolationService.count(carViolationQueryWrapper);
//                            jxqsWorkCarDetail.setViolationCount(vc);
//
//                            QueryWrapper<JxqsWorkCarDetail> queryWrapper1 = new QueryWrapper<>();
//                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getCarId, carId);
//                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getPlanId, plan.getJxqsPlanId());
//                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getWorkDate, today);
//                            List<JxqsWorkCarDetail> jxqsWorkCarDetails = jxqsWorkCarDetailService.list(queryWrapper1);
//                            if (StringUtils.isNotEmpty(jxqsWorkCarDetails) && jxqsWorkCarDetails.size() > 0) {
//                                jxqsWorkCarDetail.setJxqsWorkCarDetailId(jxqsWorkCarDetails.get(0).getJxqsWorkCarDetailId());
//                                jxqsWorkCarDetailService.updateById(jxqsWorkCarDetail);
//                            } else {
//                                jxqsWorkCarDetailService.save(jxqsWorkCarDetail);
//                            }
//                        } else if (plan.getType() == 2) { //机动作业
//                            String carIdsStr = plan.getCarIds();
//                            String[] carIds = carIdsStr.split(",");
//                            QueryWrapper<KfkCarLocation> kfkCarLocationQueryWrapper = new QueryWrapper<>();
//                            kfkCarLocationQueryWrapper.lambda().ge(KfkCarLocation::getDeviceTime, today);
//                            kfkCarLocationQueryWrapper.lambda().in(KfkCarLocation::getCarid, Arrays.asList(carIds));
//                            List<KfkCarLocation> kfkCarLocations = kfkCarLocationService.list(kfkCarLocationQueryWrapper);
//                            if (kfkCarLocations.size() > 0) {
//                                Double workKm = 0.0;
//                                Double runKm = 0.0;
//                                Date startTime = null;
//                                Map<String, List<KfkCarLocation>> map = kfkCarLocations.stream().collect(Collectors.groupingBy(KfkCarLocation::getCarid));
//                                Set<String> ks = map.keySet();
//                                for (String carId : ks) {
//                                    List<KfkCarLocation> mLocationList = map.get(carId);
//                                    if (mLocationList.size() > 0) {
//                                        Double mWorkKm = 0.0;
//                                        Double mRunKm = mLocationList.get(mLocationList.size() - 1).getMileage() - mLocationList.get(0).getMileage();
//                                        List<KfkCarLocation> kfkCarLocations1 = mLocationList.stream().filter(kfkCarLocation -> "1".equals(kfkCarLocation.getStatus())).collect(Collectors.toList());
//                                        if (kfkCarLocations1.size() > 0) {
//                                            Date mStartTime = kfkCarLocations1.get(0).getDeviceTime();
//                                            Double mileageTemp = kfkCarLocations1.get(0).getMileage();
//                                            for (int i = 0; i < mLocationList.size(); i++) {
//                                                if (i % 10 == 0) {
//                                                    if (StringUtils.isNotEmpty(mLocationList.get(i).getMileage()) && StringUtils.isNotEmpty(mLocationList.get(i).getStatus())) {
//                                                        if ("1".equals(mLocationList.get(i).getStatus()) && StringUtils.isNotEmpty(grid.getType())) {
//                                                            // 在网格内才算有效作业
//                                                            boolean inside = false;
//                                                            if (grid.getType() == 1) {
//                                                                if (grid.getAreaType() == 3) { // 圆形区域
//                                                                    inside = DistanceUtils.insideCircle(Double.valueOf(mLocationList.get(i).getLon()),
//                                                                            Double.valueOf(mLocationList.get(i).getLat()), Double.valueOf(grid.getLng()),
//                                                                            Double.valueOf(grid.getLat()), grid.getRadius());
//                                                                } else if (grid.getAreaType() == 4) { // 矩形
//                                                                    inside = DistanceUtils.insideRect(Double.valueOf(mLocationList.get(i).getLon()),
//                                                                            Double.valueOf(mLocationList.get(i).getLat()), grid.getLnglat());
//                                                                } else if (grid.getAreaType() == 5) { // 多边形区域
//                                                                    inside = DistanceUtils.insidePolygon(Double.valueOf(mLocationList.get(i).getLon()),
//                                                                            Double.valueOf(mLocationList.get(i).getLat()), grid.getLnglat());
//                                                                }
//                                                            } else if (grid.getType() == 2) { // 线路
//                                                                if (StringUtils.isNotEmpty(grid.getSectionIds())) {
//                                                                    String[] sectionIds = grid.getSectionIds().split(",");
//                                                                    QueryWrapper<Grid> queryWrapper1 = new QueryWrapper<>();
//                                                                    queryWrapper1.lambda().in(Grid::getGridId, Arrays.asList(sectionIds));
//                                                                    queryWrapper1.lambda().eq(Grid::getType, 3);
//                                                                    List<Grid> grids = gridService.list(queryWrapper1);
//                                                                    for (Grid g : grids) {
//                                                                        log.info("==判断坐标是否网格内(mileageCompleteness)线路-3,gridId:{}", g.getGridId());
//                                                                        inside = DistanceUtils.insideLine(Double.valueOf(mLocationList.get(i).getLon()),
//                                                                                Double.valueOf(mLocationList.get(i).getLat()), g.getLnglat());
//                                                                        if (inside) {
//                                                                            break;
//                                                                        }
//                                                                    }
//                                                                }
//                                                            } else if (grid.getType() == 3) { // 路段
//                                                                log.info("==判断坐标是否网格内(mileageCompleteness)路段-4,gridId:{}", grid.getGridId());
//                                                                inside = DistanceUtils.insideLine(Double.valueOf(mLocationList.get(i).getLon()),
//                                                                        Double.valueOf(mLocationList.get(i).getLat()), grid.getLnglat());
//                                                            }
//
//                                                            if (inside) {
//                                                                mWorkKm += mLocationList.get(i).getMileage() - mileageTemp;
//                                                            }
//                                                        }
//                                                        mileageTemp = mLocationList.get(i).getMileage();
//                                                    }
//                                                }
//                                            }
//                                            runKm += mRunKm;
//                                            workKm += mWorkKm;
//                                            if (StringUtils.isEmpty(startTime) || mStartTime.before(startTime)) {
//                                                startTime = mStartTime;
//                                            }
//
//                                            JxqsWorkCarDetail jxqsWorkCarDetail = new JxqsWorkCarDetail();
//                                            jxqsWorkCarDetail.setCarId(carId);
//                                            jxqsWorkCarDetail.setCarName(plan.getCarNames());
//                                            jxqsWorkCarDetail.setKmFinishRate((int) (mWorkKm * 100 / planKm));
//                                            jxqsWorkCarDetail.setPlanKm(planKm);
//                                            jxqsWorkCarDetail.setRunKm(mRunKm);
//                                            jxqsWorkCarDetail.setWorkKm(mWorkKm);
//                                            jxqsWorkCarDetail.setInvalidKm(mRunKm - mWorkKm);
//                                            jxqsWorkCarDetail.setCarStartTime(mStartTime);
//                                            jxqsWorkCarDetail.setFunType(1);
//                                            jxqsWorkCarDetail.setWorkDate(LocalDate.now());
//                                            jxqsWorkCarDetail.setPlanId(plan.getJxqsPlanId());
//                                            jxqsWorkCarDetail.setPlanName(plan.getName());
//                                            jxqsWorkCarDetail.setDepId(grid.getDepid());
//                                            jxqsWorkCarDetail.setDepName(grid.getDepName());
//                                            jxqsWorkCarDetail.setWorkCycle(plan.getWorkPeriod());
//                                            jxqsWorkCarDetail.setStatus(mWorkKm > planKm * kot ? 1 : 0);
//
//                                            QueryWrapper<CarViolation> carViolationQueryWrapper = new QueryWrapper<>();
//                                            carViolationQueryWrapper.lambda().eq(CarViolation::getCarId, carId);
//                                            carViolationQueryWrapper.lambda().like(CarViolation::getTime, today);
//                                            carViolationQueryWrapper.lambda().eq(CarViolation::getGridId, grid);
//                                            carViolationQueryWrapper.lambda().eq(CarViolation::getModule, 3);
//                                            int vc = carViolationService.count(carViolationQueryWrapper);
//                                            jxqsWorkCarDetail.setViolationCount(vc);
//
//                                            QueryWrapper<JxqsWorkCarDetail> queryWrapper1 = new QueryWrapper<>();
//                                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getCarId, carId);
//                                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getPlanId, plan.getJxqsPlanId());
//                                            queryWrapper1.lambda().eq(JxqsWorkCarDetail::getWorkDate, today);
//                                            List<JxqsWorkCarDetail> jxqsWorkCarDetails = jxqsWorkCarDetailService.list(queryWrapper1);
//                                            if (StringUtils.isNotEmpty(jxqsWorkCarDetails) && jxqsWorkCarDetails.size() > 0) {
//                                                jxqsWorkCarDetail.setJxqsWorkCarDetailId(jxqsWorkCarDetails.get(0).getJxqsWorkCarDetailId());
//                                                jxqsWorkCarDetailService.updateById(jxqsWorkCarDetail);
//                                            } else {
//                                                jxqsWorkCarDetailService.save(jxqsWorkCarDetail);
//                                            }
//                                        }
//                                    }
//                                }
//                                JxqsWorkGridDetail jxqsWorkGridDetail = new JxqsWorkGridDetail();
//                                jxqsWorkGridDetail.setCarId(carIdsStr);
//                                jxqsWorkGridDetail.setCarName(plan.getCarNames());
//                                jxqsWorkGridDetail.setFunType(1);
//                                jxqsWorkGridDetail.setGridId(plan.getGridId());
//                                jxqsWorkGridDetail.setGridName(grid.getName());
//                                jxqsWorkGridDetail.setPlanId(plan.getJxqsPlanId());
//                                jxqsWorkGridDetail.setPlanName(plan.getName());
//                                jxqsWorkGridDetail.setWorkDate(LocalDate.now());
//                                jxqsWorkGridDetail.setWorkCycle(plan.getWorkPeriod());
//                                jxqsWorkGridDetail.setWorkLevelId(grid.getLevelid());
//                                jxqsWorkGridDetail.setWorkLevelName(grid.getLevelName());
//                                jxqsWorkGridDetail.setDepId(grid.getDepid());
//                                jxqsWorkGridDetail.setDepName(grid.getDepName());
//                                jxqsWorkGridDetail.setPlanKm(planKm);
//                                jxqsWorkGridDetail.setInvalidKm(runKm - workKm);
//                                jxqsWorkGridDetail.setKmFinishRate((int) (workKm * 100 / planKm));
//                                jxqsWorkGridDetail.setCarStartTime(startTime);
//                                jxqsWorkGridDetail.setRunKm(runKm);
//                                jxqsWorkGridDetail.setWorkKm(workKm);
//                                jxqsWorkGridDetail.setStatus(workKm > planKm * kot ? 1 : 0);
//                                QueryWrapper<JxqsWorkGridDetail> queryWrapper1 = new QueryWrapper<>();
//                                queryWrapper1.lambda().eq(JxqsWorkGridDetail::getGridId, grid.getGridId());
//                                queryWrapper1.lambda().eq(JxqsWorkGridDetail::getPlanId, plan.getJxqsPlanId());
//                                queryWrapper1.lambda().eq(JxqsWorkGridDetail::getWorkDate, today);
//                                List<JxqsWorkGridDetail> jxqsWorkGridDetails = jxqsWorkGridDetailService.list(queryWrapper1);
//                                if (StringUtils.isNotEmpty(jxqsWorkGridDetails) && jxqsWorkGridDetails.size() > 0) {
//                                    jxqsWorkGridDetail.setJxqsWorkGridDetailId(jxqsWorkGridDetails.get(0).getJxqsWorkGridDetailId());
//                                    jxqsWorkGridDetailService.updateById(jxqsWorkGridDetail);
//                                } else {
//                                    jxqsWorkGridDetailService.save(jxqsWorkGridDetail);
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        }
//    }
//
//    /**
//     * 作业管理-垃圾清运-完成度分析
//     * 里程完成度、点位完成度
//     */
//    @Scheduled(cron = "0 2/10 * * * ?")
//    private void ljqyMileageCompleteness() {
//        if (timed_task) {
//
//            String today = StringUtils.dateToStr(new Date(), "yyyy-MM-dd");
//            // 里程完成率阈值
//            Jobset jobset = jobsetMapper.selectById(4);
//            Double kot = (StringUtils.isNotEmpty(jobset) && StringUtils.isNotEmpty(jobset.getKmOkThreshold())) ? jobset.getKmOkThreshold() : 1.0;
//            Double pot = (StringUtils.isNotEmpty(jobset) && StringUtils.isNotEmpty(jobset.getPointOkThreshold())) ? jobset.getPointOkThreshold() : 1.0;
//            QueryWrapper<LjqyWorkPlan> queryWrapper = new QueryWrapper<>();
//            queryWrapper.lambda().le(LjqyWorkPlan::getYxsdEndDate, today);
//            queryWrapper.lambda().ge(LjqyWorkPlan::getYxsdStartDate, today);
//            List<LjqyWorkPlan> plans = ljqyWorkPlanService.list(queryWrapper);
//            for (LjqyWorkPlan plan : plans) {
//                String carId = plan.getWorkCarId();
//                String sjdIds = plan.getSjdIds();
//                if (StringUtils.isEmpty(carId) || (StringUtils.isEmpty(sjdIds) && StringUtils.isEmpty(plan.getGridId()))) {
//                    continue;
//                }
//                // TODO: 2021/7/7 优化：只计算增量数据
//                QueryWrapper<KfkCarLocation> kfkCarLocationQueryWrapper = new QueryWrapper<>();
//                kfkCarLocationQueryWrapper.lambda().ge(KfkCarLocation::getDeviceTime, today);
//                kfkCarLocationQueryWrapper.lambda().eq(KfkCarLocation::getCarid, carId);
//                List<KfkCarLocation> kfkCarLocations = kfkCarLocationService.list(kfkCarLocationQueryWrapper);
//                if (kfkCarLocations.size() == 0) {
//                    continue;
//                }
//                // 里程完成度分析
//                if (StringUtils.isNotEmpty(carId) && StringUtils.isNotEmpty(plan.getGridId())) {
//                    Grid grid = gridService.getById(plan.getGridId());
//                    if (StringUtils.isEmpty(grid)) {
//                        continue;
//                    }
//                    Double planKm = grid.getKm();
//                    if (StringUtils.isNotEmpty(planKm)) {
//                        // TODO: 2021/7/7 在作业班组时间段内才算有效作业
//                        Double workKm = 0.0;
//                        Double runKm = kfkCarLocations.get(kfkCarLocations.size() - 1).getMileage() - kfkCarLocations.get(0).getMileage();
//                        Date startTime = kfkCarLocations.get(0).getDeviceTime();
//                        Double mileageTemp = kfkCarLocations.get(0).getMileage();
//                        for (int i = 0; i < kfkCarLocations.size(); i++) {
//                            if (i % 10 == 0) {
//                                if (StringUtils.isNotEmpty(kfkCarLocations.get(i).getMileage()) && StringUtils.isNotEmpty(grid.getType())) {
//                                    // 在网格内才算有效作业
//                                    boolean inside = false;
//                                    if (grid.getType() == 1) {
//                                        if (grid.getAreaType() == 3) { // 圆形区域
//                                            inside = DistanceUtils.insideCircle(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), Double.valueOf(grid.getLng()),
//                                                    Double.valueOf(grid.getLat()), grid.getRadius());
//                                        } else if (grid.getAreaType() == 4) { // 矩形
//                                            inside = DistanceUtils.insideRect(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                        } else if (grid.getAreaType() == 5) { // 多边形区域
//                                            inside = DistanceUtils.insidePolygon(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                    Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                        }
//                                    } else if (grid.getType() == 2) { // 线路
//                                        if (StringUtils.isNotEmpty(grid.getSectionIds())) {
//                                            String[] sectionIds = grid.getSectionIds().split(",");
//                                            QueryWrapper<Grid> queryWrapper1 = new QueryWrapper<>();
//                                            queryWrapper1.lambda().in(Grid::getGridId, Arrays.asList(sectionIds));
//                                            queryWrapper1.lambda().eq(Grid::getType, 3);
//                                            List<Grid> grids = gridService.list(queryWrapper1);
//                                            for (Grid g : grids) {
//                                                log.info("==判断坐标是否网格内(ljqyMileageCompleteness)线路-1,gridId:{}", g.getGridId());
//                                                inside = DistanceUtils.insideLine(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                        Double.valueOf(kfkCarLocations.get(i).getLat()), g.getLnglat());
//                                                if (inside) {
//                                                    break;
//                                                }
//                                            }
//                                        }
//                                    } else if (grid.getType() == 3) { // 路段
//                                        log.info("==判断坐标是否网格内(ljqyMileageCompleteness)路段-2,gridId:{}", grid.getGridId());
//                                        inside = DistanceUtils.insideLine(Double.valueOf(kfkCarLocations.get(i).getLon()),
//                                                Double.valueOf(kfkCarLocations.get(i).getLat()), grid.getLnglat());
//                                    }
//
//                                    if (inside) {
//                                        workKm += kfkCarLocations.get(i).getMileage() - mileageTemp;
//                                    }
//                                    mileageTemp = kfkCarLocations.get(i).getMileage();
//                                }
//                            }
//                        }
//                        JxqsWorkCarDetail jxqsWorkCarDetail = new JxqsWorkCarDetail();
//                        jxqsWorkCarDetail.setCarId(carId);
//                        jxqsWorkCarDetail.setCarName(plan.getWorkCarName());
//                        jxqsWorkCarDetail.setKmFinishRate((int) (workKm * 100 / planKm));
//                        jxqsWorkCarDetail.setPlanKm(planKm);
//                        jxqsWorkCarDetail.setRunKm(runKm);
//                        jxqsWorkCarDetail.setWorkKm(workKm);
//                        jxqsWorkCarDetail.setInvalidKm(runKm - workKm);
//                        jxqsWorkCarDetail.setCarStartTime(startTime);
//                        jxqsWorkCarDetail.setFunType(2);
//                        jxqsWorkCarDetail.setWorkDate(LocalDate.now());
//                        jxqsWorkCarDetail.setPlanId(plan.getLjqyWorkPlanId());
//                        jxqsWorkCarDetail.setPlanName(plan.getName());
//                        jxqsWorkCarDetail.setDepId(grid.getDepid());
//                        jxqsWorkCarDetail.setDepName(grid.getDepName());
//                        jxqsWorkCarDetail.setWorkCycle(plan.getWorkCycle());
////                    jxqsWorkCarDetail.setStatus(workKm > planKm * kot ? 1 : 0);
//                        QueryWrapper<CarViolation> carViolationQueryWrapper = new QueryWrapper<>();
//                        carViolationQueryWrapper.lambda().eq(CarViolation::getCarId, carId);
//                        carViolationQueryWrapper.lambda().like(CarViolation::getTime, today);
//                        carViolationQueryWrapper.lambda().eq(CarViolation::getModule, 4);
//                        int vc = carViolationService.count(carViolationQueryWrapper);
//                        jxqsWorkCarDetail.setViolationCount(vc);
//                        QueryWrapper<JxqsWorkCarDetail> queryWrapper1 = new QueryWrapper<>();
//                        queryWrapper1.lambda().eq(JxqsWorkCarDetail::getCarId, carId);
//                        queryWrapper1.lambda().eq(JxqsWorkCarDetail::getPlanId, plan.getLjqyWorkPlanId());
//                        queryWrapper1.lambda().eq(JxqsWorkCarDetail::getWorkDate, today);
//                        List<JxqsWorkCarDetail> jxqsWorkCarDetails = jxqsWorkCarDetailService.list(queryWrapper1);
//                        if (StringUtils.isNotEmpty(jxqsWorkCarDetails) && jxqsWorkCarDetails.size() > 0) {
//                            jxqsWorkCarDetail.setJxqsWorkCarDetailId(jxqsWorkCarDetails.get(0).getJxqsWorkCarDetailId());
//                            jxqsWorkCarDetailService.updateById(jxqsWorkCarDetail);
//                        } else {
//                            jxqsWorkCarDetailService.save(jxqsWorkCarDetail);
//                        }
//
//                        JxqsWorkGridDetail jxqsWorkGridDetail = new JxqsWorkGridDetail();
//                        jxqsWorkGridDetail.setCarId(carId);
//                        jxqsWorkGridDetail.setCarName(plan.getWorkCarName());
//                        jxqsWorkGridDetail.setFunType(2);
//                        jxqsWorkGridDetail.setGridId(plan.getGridId());
//                        jxqsWorkGridDetail.setGridName(grid.getName());
//                        jxqsWorkGridDetail.setPlanId(plan.getLjqyWorkPlanId());
//                        jxqsWorkGridDetail.setPlanName(plan.getName());
//                        jxqsWorkGridDetail.setWorkDate(LocalDate.now());
//                        jxqsWorkGridDetail.setWorkCycle(plan.getWorkCycle());
//                        jxqsWorkGridDetail.setWorkLevelId(grid.getLevelid());
//                        jxqsWorkGridDetail.setWorkLevelName(grid.getLevelName());
//                        jxqsWorkGridDetail.setDepId(grid.getDepid());
//                        jxqsWorkGridDetail.setDepName(grid.getDepName());
//                        jxqsWorkGridDetail.setPlanKm(planKm);
//                        jxqsWorkGridDetail.setInvalidKm(runKm - workKm);
//                        jxqsWorkGridDetail.setKmFinishRate((int) (workKm * 100 / planKm));
//                        jxqsWorkGridDetail.setCarStartTime(startTime);
//                        jxqsWorkGridDetail.setRunKm(runKm);
//                        jxqsWorkGridDetail.setWorkKm(workKm);
////                    jxqsWorkGridDetail.setStatus(workKm > planKm * kot ? 1 : 0);
//                        QueryWrapper<JxqsWorkGridDetail> queryWrapper2 = new QueryWrapper<>();
//                        queryWrapper2.lambda().eq(JxqsWorkGridDetail::getGridId, grid.getGridId());
//                        queryWrapper2.lambda().eq(JxqsWorkGridDetail::getPlanId, plan.getLjqyWorkPlanId());
//                        queryWrapper2.lambda().eq(JxqsWorkGridDetail::getWorkDate, today);
//                        List<JxqsWorkGridDetail> jxqsWorkGridDetails = jxqsWorkGridDetailService.list(queryWrapper2);
//                        if (StringUtils.isNotEmpty(jxqsWorkGridDetails) && jxqsWorkGridDetails.size() > 0) {
//                            jxqsWorkGridDetail.setJxqsWorkGridDetailId(jxqsWorkGridDetails.get(0).getJxqsWorkGridDetailId());
//                            jxqsWorkGridDetailService.updateById(jxqsWorkGridDetail);
//                        } else {
//                            jxqsWorkGridDetailService.save(jxqsWorkGridDetail);
//                        }
//                    }
//                }
//                // 点位完成度分析
//                if (StringUtils.isNotEmpty(sjdIds)) {
//                    String[] sjdIdss = sjdIds.split(",");
//                    QueryWrapper<TlFacilities> queryWrapper1 = new QueryWrapper<>();
//                    queryWrapper1.lambda().in(TlFacilities::getId, Arrays.asList(sjdIdss));
//                    List<TlFacilities> facilitiesList = tlFacilitiesService.list(queryWrapper1);
//                    if (facilitiesList.size() > 0) {
//                        int endPointCount = 0;
//                        for (TlFacilities facilities : facilitiesList) {
//                            String lnglat = facilities.getFacladdr();
//                            if (StringUtils.isNotEmpty(lnglat) && lnglat.contains(",")) {
//                                String[] lnglat2 = lnglat.split(",");
//                                if (lnglat2.length == 2) {
//                                    Double lng = Double.valueOf(lnglat2[0]);
//                                    Double lat = Double.valueOf(lnglat2[1]);
//                                    for (KfkCarLocation location : kfkCarLocations) {
//                                        if (StringUtils.isNotEmpty(location.getLon()) && StringUtils.isNotEmpty(location.getLat())) {
//                                            Long dt = DistanceUtils.measureDistance(lng, lat, Double.valueOf(location.getLon()), Double.valueOf(location.getLat()));
//                                            // TODO: 2021/7/19 这个地方应该是把哪一个点完成了都记录下来
//                                            //  1.避免每次都计算所有 2.轨迹上需要标记哪些点完成哪些点没完成
//                                            if (dt < 30) {
//                                                endPointCount++;
//                                                break;
//                                            }
//                                        }
//                                    }
//                                }
//                            }
//                        }
//                        int pointCount = sjdIdss.length;
//                        JxqsWorkCarDetail jxqsWorkCarDetail = new JxqsWorkCarDetail();
//                        jxqsWorkCarDetail.setCarId(carId);
//                        jxqsWorkCarDetail.setCarName(plan.getWorkCarName());
//                        jxqsWorkCarDetail.setFunType(2);
//                        jxqsWorkCarDetail.setWorkDate(LocalDate.now());
//                        jxqsWorkCarDetail.setPlanId(plan.getLjqyWorkPlanId());
//                        jxqsWorkCarDetail.setPlanName(plan.getName());
//                        jxqsWorkCarDetail.setWorkCycle(plan.getWorkCycle());
//                        jxqsWorkCarDetail.setYqydwCount(pointCount);
//                        jxqsWorkCarDetail.setSqydwCount(endPointCount);
//                        jxqsWorkCarDetail.setDwFinishRate((int) (endPointCount * 100 / pointCount));
//                        jxqsWorkCarDetail.setStatus(endPointCount > pointCount * pot ? 1 : 0);
//                        QueryWrapper<CarViolation> carViolationQueryWrapper = new QueryWrapper<>();
//                        carViolationQueryWrapper.lambda().eq(CarViolation::getCarId, carId);
//                        carViolationQueryWrapper.lambda().like(CarViolation::getTime, today);
//                        carViolationQueryWrapper.lambda().eq(CarViolation::getModule, 4);
//                        int vc = carViolationService.count(carViolationQueryWrapper);
//                        jxqsWorkCarDetail.setViolationCount(vc);
//                        QueryWrapper<JxqsWorkCarDetail> queryWrapper2 = new QueryWrapper<>();
//                        queryWrapper2.lambda().eq(JxqsWorkCarDetail::getCarId, carId);
//                        queryWrapper2.lambda().eq(JxqsWorkCarDetail::getPlanId, plan.getLjqyWorkPlanId());
//                        queryWrapper2.lambda().eq(JxqsWorkCarDetail::getWorkDate, today);
//                        List<JxqsWorkCarDetail> jxqsWorkCarDetails = jxqsWorkCarDetailService.list(queryWrapper2);
//                        if (StringUtils.isNotEmpty(jxqsWorkCarDetails) && jxqsWorkCarDetails.size() > 0) {
//                            jxqsWorkCarDetail.setJxqsWorkCarDetailId(jxqsWorkCarDetails.get(0).getJxqsWorkCarDetailId());
//                            jxqsWorkCarDetailService.updateById(jxqsWorkCarDetail);
//                        } else {
//                            jxqsWorkCarDetailService.save(jxqsWorkCarDetail);
//                        }
//
//                        JxqsWorkGridDetail jxqsWorkGridDetail = new JxqsWorkGridDetail();
//                        jxqsWorkGridDetail.setCarId(carId);
//                        jxqsWorkGridDetail.setCarName(plan.getWorkCarName());
//                        jxqsWorkGridDetail.setFunType(2);
//                        jxqsWorkGridDetail.setGridId(plan.getGridId());
//                        jxqsWorkGridDetail.setPlanId(plan.getLjqyWorkPlanId());
//                        jxqsWorkGridDetail.setPlanName(plan.getName());
//                        jxqsWorkGridDetail.setWorkDate(LocalDate.now());
//                        jxqsWorkGridDetail.setWorkCycle(plan.getWorkCycle());
//                        jxqsWorkGridDetail.setYqydwCount(pointCount);
//                        jxqsWorkGridDetail.setSqydwCount(endPointCount);
//                        jxqsWorkCarDetail.setDwFinishRate((int) (endPointCount * 100 / pointCount));
//                        jxqsWorkGridDetail.setStatus(endPointCount > pointCount * pot ? 1 : 0);
//                        QueryWrapper<JxqsWorkGridDetail> queryWrapper3 = new QueryWrapper<>();
//                        queryWrapper3.lambda().eq(JxqsWorkGridDetail::getGridId, plan.getGridId());
//                        queryWrapper3.lambda().eq(JxqsWorkGridDetail::getPlanId, plan.getLjqyWorkPlanId());
//                        queryWrapper3.lambda().eq(JxqsWorkGridDetail::getWorkDate, today);
//                        List<JxqsWorkGridDetail> jxqsWorkGridDetails = jxqsWorkGridDetailService.list(queryWrapper3);
//                        if (StringUtils.isNotEmpty(jxqsWorkGridDetails) && jxqsWorkGridDetails.size() > 0) {
//                            jxqsWorkGridDetail.setJxqsWorkGridDetailId(jxqsWorkGridDetails.get(0).getJxqsWorkGridDetailId());
//                            jxqsWorkGridDetailService.updateById(jxqsWorkGridDetail);
//                        } else {
//                            jxqsWorkGridDetailService.save(jxqsWorkGridDetail);
//                        }
//                    }
//                }
//            }
//        }
//    }

    /**
     * 定时更新车辆速度
     */
    @Scheduled(cron = "0 0 3 * * ?")
    private void updateCarSpeed() {
        if (timed_task) {

            QueryWrapper<TlCar> tlCarQueryWrapper = new QueryWrapper<>();
            tlCarQueryWrapper.lambda().gt(TlCar::getSpeed, 0);
            List<TlCar> tlCarList = tlCarMapper.selectList(tlCarQueryWrapper);
            for (TlCar tlCar : tlCarList) {
                QueryWrapper<CarTrack> trackQueryWrapper = new QueryWrapper<>();
                trackQueryWrapper.lambda().eq(CarTrack::getWorkDay, StringUtils.dateToStr(new Date(), "yyyy-MM-dd"));
                trackQueryWrapper.lambda().eq(CarTrack::getCarId, tlCar.getId());
                List<CarTrack> carTrackList = carTrackMapper.selectList(trackQueryWrapper);
                if (CollectionUtils.isEmpty(carTrackList)) {
                    tlCar.setSpeed(0);
                    tlCarMapper.updateById(tlCar);
                }
            }
        }
    }

    /**
     * 每隔10分钟执行一次
     * 定时生成车辆轨迹纠偏数据
     * 高德轨迹纠偏接口，一天只能调用30000次，每次只能上传100个坐标，一次只能查询24小时内的数据。
     */
    @Scheduled(cron = "0 1/10 * * * ?")
    private void generateCarTrackRevise() {
        if (!timed_task) {
            return;
        }
        try {
            //查询所有车辆
            List<TlCar> carAll = tlCarMapper.selectList(new QueryWrapper<>());
            if (CollectionUtils.isEmpty(carAll)) {
                return;
            }
            //遍历每辆车，获取纠偏轨迹
            for (TlCar tlCar : carAll) {
                //redis获取数据
                List<CarTrack> carTrackList = RedisUtil.getAllList(CarTrackNoReviseListKey.token, tlCar.getId(), CarTrack.class);
                if (CollectionUtils.isEmpty(carTrackList) || carTrackList.size() < 50) {
                    continue;
                }
                log.info("====carId:{},从redis获取车辆轨迹数量：{}", tlCar.getId(), carTrackList.size());
                //redis清空数据
                RedisUtil.del(CarTrackNoReviseListKey.token, tlCar.getId());
                //按照设备上传定位时间正序排序
                Collections.sort(carTrackList, (o1, o2) -> {
                    Date d1 = o1.getTimestamp();
                    Date d2 = o2.getTimestamp();
                    return d1.compareTo(d2);
                });
                //每次最多纠偏100条数据
                if (carTrackList.size() > 100) {
                    int totalSize = carTrackList.size();
                    int page = new Double(Math.ceil(totalSize / 100d)).intValue();
                    for (int i = 0; i < page; i++) {
                        int startNum = i * 100;
                        int endNum = startNum + 100;
                        if (endNum > totalSize) {
                            endNum = totalSize;
                        }
                        List<CarTrack> limit100 = new ArrayList<>();
                        for (int j = startNum; j < endNum; j++) {
                            limit100.add(carTrackList.get(j));
                        }
                        carTrackReviseService.handleCarTrackRevise(limit100);
                    }
                } else {
                    carTrackReviseService.handleCarTrackRevise(carTrackList);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


//    public void updateEmployee() {
//        QueryWrapper<EmployeeTrack> employeeTrackQueryWrapper = new QueryWrapper<>();
//        employeeTrackQueryWrapper.lambda().orderByAsc(EmployeeTrack::getTimestamp);
//        employeeTrackQueryWrapper.lambda().eq(EmployeeTrack::getWorkDay, DateUtil.format(new Date(), "yyyy-MM-dd"));
//        List<EmployeeTrack> employeeTrackList = employeeTrackMapper.selectList(employeeTrackQueryWrapper);
//        Map<String, List<EmployeeTrack>> employeeTrackCollect = employeeTrackList.stream().collect(Collectors.groupingBy(EmployeeTrack::getEmployeeId));
//        for (String key : employeeTrackCollect.keySet()) {
//            EmployeeTrack lastEmployeeTrack = employeeTrackCollect.get(key).get(employeeTrackCollect.keySet().size());
//            EmployeeTrack employeeTrack = employeeTrackCollect.get(key).get(employeeTrackCollect.keySet().size() - 1);
//            boolean stayFlag = locationUtil.checkTwoPointSame(employeeTrack.getLng(), employeeTrack.getLat(), lastEmployeeTrack.getLng(), lastEmployeeTrack.getLat());
//            TlEmployee tlEmployee = tlEmployeeMapper.selectById(key);
//            if (!stayFlag) {
////                newEmployeeTrack.setMoveSecond(lastEmployeeTrack.getMoveSecond() + 30);
//                if (null != tlEmployee) {
//                    tlEmployee.setMove("0");
//                    tlEmployeeMapper.updateById(tlEmployee);
//                }
//            } else {
//                if (null != tlEmployee) {
//                    tlEmployee.setMove("1");
//                    tlEmployeeMapper.updateById(tlEmployee);
//                }
//            }
//        }
//    }

    public void updateCarAddr() {
        //当前日期
        Date nowTime = new Date();
        //3天内的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(nowTime);
        cal.add(Calendar.DATE, -3);
        Date calTime = cal.getTime();

        List<String> carIdList = new ArrayList<>();
        //查询3天内的轨迹表
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, calTime, nowTime);
        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
        Map<String, List<CarTrack>> carTrackCollect = carTrackList.stream().collect(Collectors.groupingBy(CarTrack::getCarId));
        for (String key : carTrackCollect.keySet()) {
            carIdList.add(key);
        }
        QueryWrapper<TlCar> tlCarQueryWrapper = new QueryWrapper<>();
        tlCarQueryWrapper.lambda().notIn(TlCar::getId, carIdList);
        List<TlCar> tlCarList = tlCarMapper.selectList(tlCarQueryWrapper);
        tlCarList.forEach(tlCar -> {
            tlCar.setAddr("");
            tlCarMapper.updateById(tlCar);
        });
        System.out.println(tlCarList);
    }

    /**
     * 每隔10分钟执行一次
     * 定时生成车辆轨迹纠偏数据
     * 高德轨迹纠偏接口，一天只能调用30000次，每次只能上传100个坐标，一次只能查询24小时内的数据。
     */
    @Scheduled(cron = "0 1/5 * * * ?")
    public void updateOperationPoint() {
        if (!timed_task) {
            return;
        }
        log.debug("1111111111111111111111111111111111111" + Tools.getDateString(new Date()));
        Date date = new Date();
        QueryWrapper<RptEmployeeWork> rptEmployeeWorkQueryWrapper = new QueryWrapper<>();
        rptEmployeeWorkQueryWrapper.lambda().eq(RptEmployeeWork::getWorkDate, Tools.getYearMonthDayString(date));
        rptEmployeeWorkQueryWrapper.lambda().gt(RptEmployeeWork::getPlanEndTime, date);
        List<RptEmployeeWork> rptEmployeeWorkList = rptEmployeeWorkService.list(rptEmployeeWorkQueryWrapper);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(rptEmployeeWorkList)) {
            return;
        }
        String startTime = RedisUtil.get(CarAlarmOilTimeKeyToday.token, "updateOperationPointStartTime", String.class);
        SysDictType sysDictType = sysDictTypeService.getSysDictTypeByName("Personnel_walk_point_distance");
        if (Objects.nonNull(sysDictType)) {
            distanceFlag = Double.valueOf(sysDictType.getDictValue());
        }
        QueryWrapper<EmpWorkPoints> empWorkPointsQueryWrapper = new QueryWrapper<>();
        empWorkPointsQueryWrapper.lambda().in(EmpWorkPoints::getGridId,
                rptEmployeeWorkList.stream().map(RptEmployeeWork::getGridId).collect(toList()));
        List<EmpWorkPoints> empWorkPointsList = empWorkPointsService.list(empWorkPointsQueryWrapper);

        QueryWrapper<EmployeeTrack> employeeTrackQueryWrapper = new QueryWrapper<>();
        employeeTrackQueryWrapper.lambda().in(EmployeeTrack::getEmployeeId, rptEmployeeWorkList.stream().map(RptEmployeeWork::getEmployeeId).collect(toList()));
        if (Objects.nonNull(startTime)) {
            employeeTrackQueryWrapper.lambda().between(EmployeeTrack::getTimestamp, startTime, Tools.getDateString(date));
        } else {
            employeeTrackQueryWrapper.lambda().eq(EmployeeTrack::getWorkDay, Tools.getYearMonthDayString(date));
        }
        List<EmployeeTrack> employeeTrackList = employeeTrackMapper.selectList(employeeTrackQueryWrapper);
        log.debug("22222222222222222222222222222222222222222222222" + Tools.getDateString(new Date()));
        Boolean updateFlag = false;
        for (RptEmployeeWork rptEmployeeWork : rptEmployeeWorkList) {
            List<EmployeeTrack> trackList = employeeTrackList.stream().filter(x ->
                    x.getTimestamp().after(rptEmployeeWork.getPlanStartTime()) && x.getTimestamp().before(rptEmployeeWork.getPlanEndTime()) &&
                            rptEmployeeWork.getEmployeeId().equals(x.getEmployeeId())
            ).collect(toList());
            List<String> ids = new ArrayList<>();
            List<EmpWorkPoints> workPointsList = empWorkPointsList.stream()
                    .filter(x -> x.getGridId().equals(rptEmployeeWork.getGridId())).collect(toList());
            for (EmployeeTrack employeeTrack : trackList) {
                for (EmpWorkPoints empWorkPoints : workPointsList) {
                    if (locationUtils.getDistance(employeeTrack.getLat(), employeeTrack.getLng(), empWorkPoints.getLat().toString(), empWorkPoints.getLng().toString()) <= distanceFlag) {
                        updateFlag = true;
                        ids.add(empWorkPoints.getId());
                    }
                }
            }
            rptEmployeeWork.setAllPointsNum(workPointsList.size());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ids)) {
                updateFlag = true;
                ids = ids.stream().distinct().collect(toList());
                rptEmployeeWork.setOverPointsId(Tools.stringSplicing(ids));
                rptEmployeeWork.setOverPointsNum(ids.size());

            } else {
                rptEmployeeWork.setOverPointsNum(0);
            }
        }
        log.debug("333333333333333333333333333333333333" + Tools.getDateString(new Date()));
        RedisUtil.set(CarAlarmOilTimeKeyToday.token, "updateOperationPointStartTime", Tools.getDateString(date));
        if (updateFlag) {
            rptEmployeeWorkService.updateBatchById(rptEmployeeWorkList);
        }
        log.debug("44444444444444444444444444444444444444444" + Tools.getDateString(new Date()));
    }

    /**
     * 车辆人员自动补卡机制
     */
    @Scheduled(cron = "0 0 2,14 * * ?")
    public void automaticCardReplacementAfterWork() {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        calendar.add(Calendar.HOUR_OF_DAY, -12);
        List<EmployeePunchCard> employeePunchCardList = employeePunchCardService.list(new QueryWrapper<EmployeePunchCard>()
                .lambda().isNotNull(EmployeePunchCard::getWorkTime)
                .eq(EmployeePunchCard::getPunchCardDate, Tools.getYearMonthDayString(calendar.getTime()))
        );
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(employeePunchCardList)) {
            return;
        }
        Map<String, GridBindCheckwork> gridBindCheckworkMap = gridBindCheckWorkService.getGridBindCheckwork(new QueryWrapper<GridBindCheckwork>().lambda().eq(GridBindCheckwork::getDate, DateUtil.format(calendar.getTime(), "yyyy-MM-dd")));
        List<EmployeeTrack> employeeTrackList = employeeTrackMapper.selectList(
                new QueryWrapper<EmployeeTrack>().lambda().eq(EmployeeTrack::getWorkDay, Tools.getYearMonthDayString(calendar.getTime()))
                        .orderByDesc(EmployeeTrack::getTimestamp)
        );
        List<CarTrack> carTrackList = carTrackService.list(
                new QueryWrapper<CarTrack>().lambda().eq(CarTrack::getWorkDay, Tools.getYearMonthDayString(calendar.getTime()))
                        .orderByDesc(CarTrack::getTimestamp)
        );
        Map<String, List<EmployeeTrack>> employeeTrackMap = GroupingByUtils.getGroupingForMapList(
                employeeTrackList, EmployeeTrack::getEmployeeId);
        Map<String, List<CarTrack>> carTrackMap = GroupingByUtils.getGroupingForMapList(
                carTrackList, CarTrack::getCarId);
        QueryWrapper<Grid> gridQueryWrapper = new QueryWrapper<>();
        List<Grid> gridList = gridService.list(gridQueryWrapper);
        gridQueryWrapper.lambda().eq(Grid::getGridType, 0);
        Map<String, Grid> gridMap = GroupingByUtils.getGroupingForMapEntity(gridList, Grid::getGridId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
        for (EmployeePunchCard employeePunchCard : employeePunchCardList) {
            if (Objects.nonNull(employeePunchCard.getManCarType()) && employeePunchCard.getManCarType().equals(1)) {
                EmployeeTrack employeeTrack = getTrackInGrid(employeeTrackList, EmployeeTrack::getLng, EmployeeTrack::getLat, gridMap.get(employeePunchCard.getGridId()));
                if (Objects.nonNull(employeeTrack)) {
                    employeePunchCard.setAfterWorkTime(DateUtil.format(employeeTrack.getTimestamp(), "HH:mm:ss"));
                    GridBindCheckwork gridBindCheckwork = gridBindCheckworkMap.get(employeePunchCard.getGridBindCheckworkId());
                    if (Objects.nonNull(gridBindCheckwork) && gridBindCheckwork.getEndTime().before(employeeTrack.getTimestamp())) {
                        employeePunchCard.setLeaveEarly(0);
                    } else {
                        employeePunchCard.setLeaveEarly(1);
                    }
                } else {
                    employeePunchCard.setNoWork(1);
                }
            }
            if (Objects.nonNull(employeePunchCard.getManCarType()) && employeePunchCard.getManCarType().equals(2)) {
                CarTrack carTrack = getTrackInGrid(carTrackList, CarTrack::getLng, CarTrack::getLat, gridMap.get(employeePunchCard.getGridId()));
                if (Objects.nonNull(carTrack)) {
                    employeePunchCard.setAfterWorkTime(DateUtil.format(carTrack.getTimestamp(), "HH:mm:ss"));
                    GridBindCheckwork gridBindCheckwork = gridBindCheckworkMap.get(employeePunchCard.getGridBindCheckworkId());
                    if (Objects.nonNull(gridBindCheckwork) && gridBindCheckwork.getEndTime().before(carTrack.getTimestamp())) {
                        employeePunchCard.setLeaveEarly(1);
                    } else {
                        employeePunchCard.setLeaveEarly(0);
                    }
                } else {
                    employeePunchCard.setNoWork(1);
                }
            }
        }
        employeePunchCardService.updateBatchById(employeePunchCardList);
    }

    private static <T, K> T getTrackInGrid(List<T> tList, Function<? super T, ? extends K> getLng, Function<? super T, ? extends K> getLat, Grid grid) {
        for (T t : tList) {
            if (DistanceUtils.insideGrid(Double.valueOf((String) getLng.apply(t)), Double.valueOf((String) getLat.apply(t)), grid)) {
                return t;
            }
        }
        return null;
    }

}
